diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0018-input-ti_tsc-Enable-shared-IRQ-TSC.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0018-input-ti_tsc-Enable-shared-IRQ-TSC.patch index 245a8090..740e79e2 100644 --- a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0018-input-ti_tsc-Enable-shared-IRQ-TSC.patch +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0018-input-ti_tsc-Enable-shared-IRQ-TSC.patch @@ -1,7 +1,7 @@ -From 4028c98c01d5a5496fe047528173e4ca1018babb Mon Sep 17 00:00:00 2001 +From 67f2bb9789a72863d4ad6cf96a597dfcccbbf8dc Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Fri, 28 Jun 2013 00:45:20 +0100 -Subject: [PATCH 18/20] input : ti_tsc : Enable shared IRQ TSC +Subject: [PATCH 18/19] input : ti_tsc : Enable shared IRQ TSC Touchscreen and ADC share the same IRQ line from parent MFD core. Previously only Touchscreen was interrupt based. @@ -13,7 +13,8 @@ Signed-off-by: Patil, Rachna Acked-by: Vaibhav Hiremath --- drivers/input/touchscreen/ti_am335x_tsc.c | 23 +++++++++++++++-------- - 1 file changed, 15 insertions(+), 8 deletions(-) + include/linux/mfd/ti_am335x_tscadc.h | 13 ++++++++++++- + 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index f0acdca..8933c91 100644 @@ -69,6 +70,55 @@ index f0acdca..8933c91 100644 if (err) { dev_err(&pdev->dev, "failed to allocate irq.\n"); goto err_free_mem; +diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h +index 17c0cba..3a9c00f 100644 +--- a/include/linux/mfd/ti_am335x_tscadc.h ++++ b/include/linux/mfd/ti_am335x_tscadc.h +@@ -46,17 +46,23 @@ + /* Step Enable */ + #define STEPENB_MASK (0x1FFFF << 0) + #define STEPENB(val) ((val) << 0) ++#define ENB(val) (1 << (val)) ++#define STPENB_STEPENB STEPENB(0x1FFFF) ++#define STPENB_STEPENB_TC STEPENB(0x1FFF) + + /* IRQ enable */ + #define IRQENB_HW_PEN BIT(0) + #define IRQENB_FIFO0THRES BIT(2) + #define IRQENB_FIFO1THRES BIT(5) + #define IRQENB_PENUP BIT(9) ++#define IRQENB_FIFO1OVRRUN BIT(6) ++#define IRQENB_FIFO1UNDRFLW BIT(7) + + /* Step Configuration */ + #define STEPCONFIG_MODE_MASK (3 << 0) + #define STEPCONFIG_MODE(val) ((val) << 0) + #define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2) ++#define STEPCONFIG_MODE_SWCNT STEPCONFIG_MODE(1) + #define STEPCONFIG_AVG_MASK (7 << 2) + #define STEPCONFIG_AVG(val) ((val) << 2) + #define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4) +@@ -124,7 +130,8 @@ + #define MAX_CLK_DIV 7 + #define TOTAL_STEPS 16 + #define TOTAL_CHANNELS 8 +- ++#define FIFO1_THRESHOLD 19 ++#define FIFO_SIZE 64 + /* + * ADC runs at 3MHz, and it takes + * 15 cycles to latch one data output. +@@ -159,6 +166,10 @@ struct ti_tscadc_dev { + + /* adc device */ + struct adc_device *adc; ++ ++ /* Context save */ ++ unsigned int irqstat; ++ unsigned int ctrl; + }; + + static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p) -- -1.8.2.1 +1.9.2 diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0020-iio-ti_am335x_adc-Add-IIO-map-interface.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0019-iio-ti_am335x_adc-Add-IIO-map-interface.patch similarity index 79% rename from common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0020-iio-ti_am335x_adc-Add-IIO-map-interface.patch rename to common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0019-iio-ti_am335x_adc-Add-IIO-map-interface.patch index e8cab3c3..050405c2 100644 --- a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0020-iio-ti_am335x_adc-Add-IIO-map-interface.patch +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0019-iio-ti_am335x_adc-Add-IIO-map-interface.patch @@ -1,7 +1,7 @@ -From 83413d509a620b48c06aa6fe04cd038916614554 Mon Sep 17 00:00:00 2001 +From 616716a527a6e9393e0aed38a48ed342bb67e407 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Sat, 27 Jul 2013 13:06:21 +0100 -Subject: [PATCH 20/20] iio: ti_am335x_adc: Add IIO map interface +Subject: [PATCH 19/19] iio: ti_am335x_adc: Add IIO map interface Add an IIO map interface that consumers can use. @@ -12,18 +12,18 @@ Signed-off-by: Zubair Lutfullah 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c -index d626508..a172dfb 100644 +index f78d2c1..c380142 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c -@@ -38,6 +38,7 @@ +@@ -33,6 +33,7 @@ struct tiadc_device { struct ti_tscadc_dev *mfd_tscadc; int channels; + struct iio_map *map; u8 channel_line[8]; u8 channel_step[8]; - struct work_struct poll_work; -@@ -300,13 +301,16 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) + }; +@@ -105,13 +106,16 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) struct tiadc_device *adc_dev = iio_priv(indio_dev); struct iio_chan_spec *chan_array; struct iio_chan_spec *chan; @@ -43,10 +43,10 @@ index d626508..a172dfb 100644 chan = chan_array; for (i = 0; i < channels; i++, chan++) { -@@ -323,12 +327,44 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) - } +@@ -128,12 +132,44 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) indio_dev->channels = chan_array; + + + map = kcalloc(channels + 1, sizeof(struct iio_map), GFP_KERNEL); + if (map == NULL) { @@ -88,8 +88,8 @@ index d626508..a172dfb 100644 } static int tiadc_read_raw(struct iio_dev *indio_dev, -@@ -436,8 +472,10 @@ static int tiadc_probe(struct platform_device *pdev) - tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD); +@@ -246,12 +282,16 @@ static int tiadc_probe(struct platform_device *pdev) + tiadc_step_config(adc_dev); err = tiadc_channel_init(indio_dev, adc_dev->channels); - if (err < 0) @@ -98,11 +98,6 @@ index d626508..a172dfb 100644 goto err_free_device; + } - INIT_WORK(&adc_dev->poll_work, &tiadc_adc_work); - init_waitqueue_head(&adc_dev->wq_data_avail); -@@ -453,8 +491,10 @@ static int tiadc_probe(struct platform_device *pdev) - goto err_unregister; - err = iio_device_register(indio_dev); - if (err) + if (err) { @@ -113,5 +108,5 @@ index d626508..a172dfb 100644 platform_set_drvdata(pdev, indio_dev); -- -1.8.2.1 +1.9.2 diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0019-iio-ti_am335x_adc-Add-continuous-sampling-and-trigge.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0019-iio-ti_am335x_adc-Add-continuous-sampling-and-trigge.patch deleted file mode 100644 index 0394bbcd..00000000 --- a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/adc/0019-iio-ti_am335x_adc-Add-continuous-sampling-and-trigge.patch +++ /dev/null @@ -1,530 +0,0 @@ -From a6731479e3a997f10fb9c0b9c701fe98b42f543a Mon Sep 17 00:00:00 2001 -From: Zubair Lutfullah -Date: Sat, 27 Jul 2013 12:34:04 +0100 -Subject: [PATCH 19/20] iio: ti_am335x_adc: Add continuous sampling and trigger - support - -Previously the driver had only one-shot reading functionality. -This patch adds triggered buffer support to the driver. -A buffer of samples can now be read via /dev/iio. - -Patil Rachna (TI) laid the ground work for ADC HW register access. -Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs. - -I fixed channel scanning so multiple ADC channels can be read -simultaneously and pushed to userspace. -Restructured the driver to fit IIO ABI. -And added trigger support. - -Signed-off-by: Zubair Lutfullah -Acked-by: Greg Kroah-Hartman -Signed-off-by: Russ Dill ---- - drivers/iio/adc/ti_am335x_adc.c | 335 ++++++++++++++++++++++++++++------- - include/linux/mfd/ti_am335x_tscadc.h | 13 +- - 2 files changed, 287 insertions(+), 61 deletions(-) - -diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c -index f78d2c1..d626508 100644 ---- a/drivers/iio/adc/ti_am335x_adc.c -+++ b/drivers/iio/adc/ti_am335x_adc.c -@@ -26,15 +26,26 @@ - #include - #include - #include -- - #include - #include -+#include -+#include -+#include -+#include -+#include -+#include - - struct tiadc_device { - struct ti_tscadc_dev *mfd_tscadc; - int channels; - u8 channel_line[8]; - u8 channel_step[8]; -+ struct work_struct poll_work; -+ wait_queue_head_t wq_data_avail; -+ bool data_avail; -+ u32 *inputbuffer; -+ int sample_count; -+ int irq; - }; - - static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) -@@ -57,27 +68,28 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev) - return step_en; - } - --static void tiadc_step_config(struct tiadc_device *adc_dev) -+static void tiadc_step_config(struct iio_dev *indio_dev) - { -+ struct tiadc_device *adc_dev = iio_priv(indio_dev); - unsigned int stepconfig; -- int i, steps; -+ int i, steps, chan; - - /* - * There are 16 configurable steps and 8 analog input - * lines available which are shared between Touchscreen and ADC. -- * - * Steps backwards i.e. from 16 towards 0 are used by ADC - * depending on number of input lines needed. - * Channel would represent which analog input - * needs to be given to ADC to digitalize data. - */ -- - steps = TOTAL_STEPS - adc_dev->channels; -- stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; -+ if (iio_buffer_enabled(indio_dev)) -+ stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1 -+ | STEPCONFIG_MODE_SWCNT; -+ else -+ stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; - - for (i = 0; i < adc_dev->channels; i++) { -- int chan; -- - chan = adc_dev->channel_line[i]; - tiadc_writel(adc_dev, REG_STEPCONFIG(steps), - stepconfig | STEPCONFIG_INP(chan)); -@@ -86,7 +98,190 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) - adc_dev->channel_step[i] = steps; - steps++; - } -+} -+ -+static irqreturn_t tiadc_irq(int irq, void *private) -+{ -+ struct iio_dev *idev = private; -+ struct tiadc_device *adc_dev = iio_priv(idev); -+ unsigned int status, config; -+ status = tiadc_readl(adc_dev, REG_IRQSTATUS); -+ -+ /* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */ -+ if (status & IRQENB_FIFO1OVRRUN) { -+ config = tiadc_readl(adc_dev, REG_CTRL); -+ config &= ~(CNTRLREG_TSCSSENB); -+ tiadc_writel(adc_dev, REG_CTRL, config); -+ tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN | -+ IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES); -+ tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB)); -+ return IRQ_HANDLED; -+ } else if (status & IRQENB_FIFO1THRES) { -+ /* Wake adc_work that pushes FIFO data to iio buffer */ -+ tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES); -+ adc_dev->data_avail = 1; -+ wake_up_interruptible(&adc_dev->wq_data_avail); -+ return IRQ_HANDLED; -+ } else -+ return IRQ_NONE; -+} -+ -+static irqreturn_t tiadc_trigger_h(int irq, void *p) -+{ -+ struct iio_poll_func *pf = p; -+ struct iio_dev *indio_dev = pf->indio_dev; -+ struct tiadc_device *adc_dev = iio_priv(indio_dev); -+ unsigned int config; -+ -+ schedule_work(&adc_dev->poll_work); -+ config = tiadc_readl(adc_dev, REG_CTRL); -+ tiadc_writel(adc_dev, REG_CTRL, config & ~CNTRLREG_TSCSSENB); -+ tiadc_writel(adc_dev, REG_CTRL, config | CNTRLREG_TSCSSENB); -+ -+ tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES | -+ IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW); -+ tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES -+ | IRQENB_FIFO1OVRRUN); -+ -+ iio_trigger_notify_done(indio_dev->trig); -+ return IRQ_HANDLED; -+} -+ -+static int tiadc_buffer_preenable(struct iio_dev *indio_dev) -+{ -+ return iio_sw_buffer_preenable(indio_dev); -+} -+ -+static int tiadc_buffer_postenable(struct iio_dev *indio_dev) -+{ -+ struct tiadc_device *adc_dev = iio_priv(indio_dev); -+ struct iio_buffer *buffer = indio_dev->buffer; -+ unsigned int enb, stepnum; -+ u8 bit; -+ -+ tiadc_step_config(indio_dev); -+ tiadc_writel(adc_dev, REG_SE, 0x00); -+ for_each_set_bit(bit, buffer->scan_mask, -+ adc_dev->channels) { -+ struct iio_chan_spec const *chan = indio_dev->channels + bit; -+ /* -+ * There are a total of 16 steps available -+ * that are shared between ADC and touchscreen. -+ * We start configuring from step 16 to 0 incase of -+ * ADC. Hence the relation between input channel -+ * and step for ADC would be as below. -+ */ -+ stepnum = chan->channel + 9; -+ enb = tiadc_readl(adc_dev, REG_SE); -+ enb |= (1 << stepnum); -+ tiadc_writel(adc_dev, REG_SE, enb); -+ } -+ -+ return iio_triggered_buffer_postenable(indio_dev); -+} -+ -+static int tiadc_buffer_predisable(struct iio_dev *indio_dev) -+{ -+ struct tiadc_device *adc_dev = iio_priv(indio_dev); -+ int fifo1count, i, read, config; -+ -+ config = tiadc_readl(adc_dev, REG_CTRL); -+ config &= ~(CNTRLREG_TSCSSENB); -+ tiadc_writel(adc_dev, REG_CTRL, config); -+ tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | -+ IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); -+ tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB_TC); -+ -+ /* Flush FIFO of any leftover data */ -+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); -+ for (i = 0; i < fifo1count; i++) -+ read = tiadc_readl(adc_dev, REG_FIFO1); -+ -+ return iio_triggered_buffer_predisable(indio_dev); -+} -+ -+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev) -+{ -+ struct tiadc_device *adc_dev = iio_priv(indio_dev); -+ int config; -+ -+ tiadc_step_config(indio_dev); -+ config = tiadc_readl(adc_dev, REG_CTRL); -+ tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB)); -+ -+ return 0; -+} -+ -+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = { -+ .preenable = &tiadc_buffer_preenable, -+ .postenable = &tiadc_buffer_postenable, -+ .predisable = &tiadc_buffer_predisable, -+ .postdisable = &tiadc_buffer_postdisable, -+}; -+ -+static void tiadc_adc_work(struct work_struct *work_s) -+{ -+ struct tiadc_device *adc_dev = -+ container_of(work_s, struct tiadc_device, poll_work); -+ struct iio_dev *indio_dev = iio_priv_to_dev(adc_dev); -+ struct iio_buffer *buffer = indio_dev->buffer; -+ int i, j, k, fifo1count, read; -+ unsigned int config; -+ int size_to_acquire = buffer->access->get_length(buffer); -+ int sample_count = 0; -+ u32 *data; -+ -+ adc_dev->data_avail = 0; -+ data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); -+ if (data == NULL) -+ goto out; -+ -+ while (sample_count < size_to_acquire) { -+ tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES); -+ tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES); -+ -+ wait_event_interruptible(adc_dev->wq_data_avail, -+ (adc_dev->data_avail == 1)); -+ adc_dev->data_avail = 0; -+ -+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); -+ if (fifo1count * sizeof(u32) < -+ buffer->access->get_bytes_per_datum(buffer)) -+ continue; -+ -+ sample_count = sample_count + fifo1count; -+ for (k = 0; k < fifo1count; k = k + i) { -+ for (i = 0, j = 0; i < (indio_dev->scan_bytes)/4; i++) { -+ read = tiadc_readl(adc_dev, REG_FIFO1); -+ data[i] = read & FIFOREAD_DATA_MASK; -+ } -+ iio_push_to_buffers(indio_dev, (u8 *) data); -+ } -+ } -+out: -+ tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | -+ IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); -+ config = tiadc_readl(adc_dev, REG_CTRL); -+ tiadc_writel(adc_dev, REG_CTRL, config & ~CNTRLREG_TSCSSENB); -+} -+ -+irqreturn_t tiadc_iio_pollfunc(int irq, void *p) -+{ -+ struct iio_poll_func *pf = p; -+ struct iio_dev *indio_dev = pf->indio_dev; -+ struct tiadc_device *adc_dev = iio_priv(indio_dev); -+ int i, fifo1count, read; - -+ tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | -+ IRQENB_FIFO1OVRRUN | -+ IRQENB_FIFO1UNDRFLW)); -+ -+ /* Flush FIFO before trigger */ -+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); -+ for (i = 0; i < fifo1count; i++) -+ read = tiadc_readl(adc_dev, REG_FIFO1); -+ -+ return IRQ_WAKE_THREAD; - } - - static const char * const chan_name_ain[] = { -@@ -121,13 +316,13 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) - chan->channel = adc_dev->channel_line[i]; - chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT; - chan->datasheet_name = chan_name_ain[chan->channel]; -+ chan->scan_index = i; - chan->scan_type.sign = 'u'; - chan->scan_type.realbits = 12; - chan->scan_type.storagebits = 32; - } - - indio_dev->channels = chan_array; -- - return 0; - } - -@@ -142,61 +337,53 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, - { - struct tiadc_device *adc_dev = iio_priv(indio_dev); - int i, map_val; -- unsigned int fifo1count, read, stepid; -- u32 step = UINT_MAX; -- bool found = false; -- u32 step_en; -- unsigned long timeout = jiffies + usecs_to_jiffies -- (IDLE_TIMEOUT * adc_dev->channels); -- step_en = get_adc_step_mask(adc_dev); -- am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); -- -- /* Wait for ADC sequencer to complete sampling */ -- while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) { -- if (time_after(jiffies, timeout)) -- return -EAGAIN; -- } -- map_val = chan->channel + TOTAL_CHANNELS; -- /* -- * When the sub-system is first enabled, -- * the sequencer will always start with the -- * lowest step (1) and continue until step (16). -- * For ex: If we have enabled 4 ADC channels and -- * currently use only 1 out of them, the -- * sequencer still configures all the 4 steps, -- * leading to 3 unwanted data. -- * Hence we need to flush out this data. -- */ -- -- for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) { -- if (chan->channel == adc_dev->channel_line[i]) { -- step = adc_dev->channel_step[i]; -- break; -- } -- } -- if (WARN_ON_ONCE(step == UINT_MAX)) -- return -EINVAL; -- -- fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); -- for (i = 0; i < fifo1count; i++) { -- read = tiadc_readl(adc_dev, REG_FIFO1); -- stepid = read & FIFOREAD_CHNLID_MASK; -- stepid = stepid >> 0x10; -+ unsigned int fifo1count, read, stepid, step_en; - -- if (stepid == map_val) { -- read = read & FIFOREAD_DATA_MASK; -- found = true; -- *val = read; -+ if (iio_buffer_enabled(indio_dev)) -+ return -EBUSY; -+ else { -+ unsigned long timeout = jiffies + usecs_to_jiffies -+ (IDLE_TIMEOUT * adc_dev->channels); -+ step_en = get_adc_step_mask(adc_dev); -+ am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); -+ -+ /* Wait for ADC sequencer to complete sampling */ -+ while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) { -+ if (time_after(jiffies, timeout)) -+ return -EAGAIN; -+ } -+ map_val = chan->channel + TOTAL_CHANNELS; -+ -+ /* -+ * When the sub-system is first enabled, -+ * the sequencer will always start with the -+ * lowest step (1) and continue until step (16). -+ * For ex: If we have enabled 4 ADC channels and -+ * currently use only 1 out of them, the -+ * sequencer still configures all the 4 steps, -+ * leading to 3 unwanted data. -+ * Hence we need to flush out this data. -+ */ -+ -+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); -+ for (i = 0; i < fifo1count; i++) { -+ read = tiadc_readl(adc_dev, REG_FIFO1); -+ stepid = read & FIFOREAD_CHNLID_MASK; -+ stepid = stepid >> 0x10; -+ -+ if (stepid == map_val) { -+ read = read & FIFOREAD_DATA_MASK; -+ *val = read; -+ return IIO_VAL_INT; -+ } - } -+ return -EAGAIN; - } -- -- if (found == false) -- return -EBUSY; -- return IIO_VAL_INT; - } - - static const struct iio_info tiadc_info = { - .read_raw = &tiadc_read_raw, -+ .driver_module = THIS_MODULE, - }; - - static int tiadc_probe(struct platform_device *pdev) -@@ -237,18 +424,34 @@ static int tiadc_probe(struct platform_device *pdev) - } - adc_dev->channels = channels; - } -+ adc_dev->channels = channels; -+ adc_dev->irq = adc_dev->mfd_tscadc->irq; - - indio_dev->dev.parent = &pdev->dev; - indio_dev->name = dev_name(&pdev->dev); - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->info = &tiadc_info; - -- tiadc_step_config(adc_dev); -+ tiadc_step_config(indio_dev); -+ tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD); - - err = tiadc_channel_init(indio_dev, adc_dev->channels); - if (err < 0) - goto err_free_device; - -+ INIT_WORK(&adc_dev->poll_work, &tiadc_adc_work); -+ init_waitqueue_head(&adc_dev->wq_data_avail); -+ -+ err = request_irq(adc_dev->irq, tiadc_irq, IRQF_SHARED, -+ indio_dev->name, indio_dev); -+ if (err) -+ goto err_free_irq; -+ -+ err = iio_triggered_buffer_setup(indio_dev, &tiadc_iio_pollfunc, -+ &tiadc_trigger_h, &tiadc_buffer_setup_ops); -+ if (err) -+ goto err_unregister; -+ - err = iio_device_register(indio_dev); - if (err) - goto err_free_channels; -@@ -257,6 +460,10 @@ static int tiadc_probe(struct platform_device *pdev) - - return 0; - -+err_unregister: -+ iio_buffer_unregister(indio_dev); -+err_free_irq: -+ free_irq(adc_dev->irq, indio_dev); - err_free_channels: - tiadc_channels_remove(indio_dev); - err_free_device: -@@ -271,7 +478,9 @@ static int tiadc_remove(struct platform_device *pdev) - struct tiadc_device *adc_dev = iio_priv(indio_dev); - u32 step_en; - -+ free_irq(adc_dev->irq, indio_dev); - iio_device_unregister(indio_dev); -+ iio_buffer_unregister(indio_dev); - tiadc_channels_remove(indio_dev); - - step_en = get_adc_step_mask(adc_dev); -@@ -309,10 +518,16 @@ static int tiadc_resume(struct device *dev) - - /* Make sure ADC is powered up */ - restore = tiadc_readl(adc_dev, REG_CTRL); -- restore &= ~(CNTRLREG_POWERDOWN); -+ restore &= ~(CNTRLREG_TSCSSENB); - tiadc_writel(adc_dev, REG_CTRL, restore); - -- tiadc_step_config(adc_dev); -+ tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD); -+ tiadc_step_config(indio_dev); -+ -+ /* Make sure ADC is powered up */ -+ restore &= ~(CNTRLREG_POWERDOWN); -+ restore |= CNTRLREG_TSCSSENB; -+ tiadc_writel(adc_dev, REG_CTRL, restore); - - return 0; - } -diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h -index 17c0cba..3a9c00f 100644 ---- a/include/linux/mfd/ti_am335x_tscadc.h -+++ b/include/linux/mfd/ti_am335x_tscadc.h -@@ -46,17 +46,23 @@ - /* Step Enable */ - #define STEPENB_MASK (0x1FFFF << 0) - #define STEPENB(val) ((val) << 0) -+#define ENB(val) (1 << (val)) -+#define STPENB_STEPENB STEPENB(0x1FFFF) -+#define STPENB_STEPENB_TC STEPENB(0x1FFF) - - /* IRQ enable */ - #define IRQENB_HW_PEN BIT(0) - #define IRQENB_FIFO0THRES BIT(2) - #define IRQENB_FIFO1THRES BIT(5) - #define IRQENB_PENUP BIT(9) -+#define IRQENB_FIFO1OVRRUN BIT(6) -+#define IRQENB_FIFO1UNDRFLW BIT(7) - - /* Step Configuration */ - #define STEPCONFIG_MODE_MASK (3 << 0) - #define STEPCONFIG_MODE(val) ((val) << 0) - #define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2) -+#define STEPCONFIG_MODE_SWCNT STEPCONFIG_MODE(1) - #define STEPCONFIG_AVG_MASK (7 << 2) - #define STEPCONFIG_AVG(val) ((val) << 2) - #define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4) -@@ -124,7 +130,8 @@ - #define MAX_CLK_DIV 7 - #define TOTAL_STEPS 16 - #define TOTAL_CHANNELS 8 -- -+#define FIFO1_THRESHOLD 19 -+#define FIFO_SIZE 64 - /* - * ADC runs at 3MHz, and it takes - * 15 cycles to latch one data output. -@@ -159,6 +166,10 @@ struct ti_tscadc_dev { - - /* adc device */ - struct adc_device *adc; -+ -+ /* Context save */ -+ unsigned int irqstat; -+ unsigned int ctrl; - }; - - static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p) --- -1.8.2.1 - diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0001-Make-the-McASP-code-generic-again-remove-all-hardcod.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0001-Make-the-McASP-code-generic-again-remove-all-hardcod.patch new file mode 100644 index 00000000..6d54323a --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0001-Make-the-McASP-code-generic-again-remove-all-hardcod.patch @@ -0,0 +1,169 @@ +From 33e9ace7e6bc432ee4455ffcb827246e2df8fb54 Mon Sep 17 00:00:00 2001 +From: Darren Etheridge +Date: Mon, 1 Jul 2013 16:06:55 -0500 +Subject: [PATCH] Make the McASP code generic again, remove all hardcoding + +After adding the HDMI audio, the McASP driver was left in +a mess, and broken when used with other capes. This patch +puts things right, and moves the necessary config code into +davinci-evm.c where it belongs. + +Signed-off-by: Darren Etheridge +--- + sound/soc/davinci/davinci-evm.c | 48 +++++++++++++++++++++++++++---------- + sound/soc/davinci/davinci-mcasp.c | 12 ++++----- + 2 files changed, 40 insertions(+), 20 deletions(-) + +diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c +index 7a7fc47..421feb0 100644 +--- a/sound/soc/davinci/davinci-evm.c ++++ b/sound/soc/davinci/davinci-evm.c +@@ -146,6 +146,32 @@ static const struct snd_soc_dapm_route audio_map[] = { + }; + + /* Logic for a aic3x as connected on a davinci-evm */ ++static int evm_tda998x_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ int ret; ++ ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 1); ++ if (ret < 0) ++ return ret; ++ ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, 1, 8); ++ if (ret < 0) ++ return ret; ++ ++ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN); ++ if (ret < 0) ++ return ret; ++ ++ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_NF); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++/* Logic for a aic3x as connected on a davinci-evm */ + static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) + { + struct snd_soc_codec *codec = rtd->codec; +@@ -380,11 +406,12 @@ static int davinci_evm_probe(struct platform_device *pdev) + evm_dai.name = "NXP TDA HDMI Chip"; + evm_dai.stream_name = "HDMI"; + evm_dai.codec_dai_name = "nxp-hdmi-hifi"; ++ evm_dai.init = evm_tda998x_init; + +- /* +- * Move GPIO handling out of the probe, if probe gets ++ /* ++ * Move GPIO handling out of the probe, if probe gets + * deferred, the gpio will have been claimed on previous +- * probe and will fail on the second and susequent probes ++ * probe and will fail on the second and susequent probes + */ + clk_gpio = of_get_named_gpio(np, "mcasp_clock_enable", 0); + if (clk_gpio < 0) { +@@ -398,11 +425,8 @@ static int davinci_evm_probe(struct platform_device *pdev) + return -EINVAL; + } + gpio_set_value(clk_gpio, 1); +- evm_dai.dai_fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF; + break; +- + } +- + + evm_dai.codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0); + if (!evm_dai.codec_of_node) +@@ -421,9 +445,9 @@ static int davinci_evm_probe(struct platform_device *pdev) + return ret; + + ret = snd_soc_register_card(&evm_soc_card); +- if (ret) { ++ if (ret) + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); +- } ++ + return ret; + } + +@@ -460,9 +484,8 @@ static int __init evm_init(void) + * If dtb is there, the devices will be created dynamically. + * Only register platfrom driver structure. + */ +- if (of_have_populated_dt()) { +- return platform_driver_register(&davinci_evm_driver); +- } ++ if (of_have_populated_dt()) ++ return platform_driver_register(&davinci_evm_driver); + #endif + + if (machine_is_davinci_evm()) { +@@ -483,9 +506,8 @@ static int __init evm_init(void) + } else if (machine_is_davinci_da850_evm()) { + evm_snd_dev_data = &da850_snd_soc_card; + index = 0; +- } else { ++ } else + return -EINVAL; +- } + + evm_snd_device = platform_device_alloc("soc-audio", index); + if (!evm_snd_device) +diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c +index bef4e72..83232c6 100644 +--- a/sound/soc/davinci/davinci-mcasp.c ++++ b/sound/soc/davinci/davinci-mcasp.c +@@ -484,6 +484,10 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, + mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); + mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); + break; ++ case SND_SOC_DAIFMT_I2S: ++ mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); ++ mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); ++ break; + default: + /* configure a full-word SYNC pulse (LRCLK) */ + mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); +@@ -498,16 +502,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + /* codec is clock and frame slave */ +- mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | ACLKXDIV(7)); +- mcasp_set_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(0)); +- mcasp_clr_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); ++ mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); + mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); + + mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); + mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); + + mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX); +- mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, AHCLKX); + break; + case SND_SOC_DAIFMT_CBM_CFS: + /* codec is clock master and frame slave */ +@@ -749,7 +750,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* bit stream is MSB first with no delay */ + /* DSP_B mode */ +- mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); + mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); + mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); + +@@ -759,8 +759,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) + else + printk(KERN_ERR "playback tdm slot %d not supported\n", + dev->tdm_slots); +- mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); +- mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); + } else { + /* bit stream is MSB first with no delay */ + /* DSP_B mode */ +-- +1.7.0.4 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0002-ASoc-Davinci-EVM-Config-12MHz-CLK-for-AIC3x-Codec.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0002-ASoc-Davinci-EVM-Config-12MHz-CLK-for-AIC3x-Codec.patch new file mode 100644 index 00000000..1c24c57d --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0002-ASoc-Davinci-EVM-Config-12MHz-CLK-for-AIC3x-Codec.patch @@ -0,0 +1,49 @@ +From 887cbba2db4a9333db46f325ed12ae37fa658c18 Mon Sep 17 00:00:00 2001 +From: Cody Lacey +Date: Fri, 18 Oct 2013 12:31:38 -0500 +Subject: [PATCH 1/2] ASoc: Davinci-EVM: Config 12MHz CLK for AIC3x Codec + +The AIC3x Codec needs a 12MHz clock source. If the +codec MCLK is connected to McASP AHCLKX or AHCLKR +then the 24MHz internal clock needs to be divided +by 2. +--- + sound/soc/davinci/davinci-evm.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c +index 421feb0..1d9e9ce 100644 +--- a/sound/soc/davinci/davinci-evm.c ++++ b/sound/soc/davinci/davinci-evm.c +@@ -145,7 +145,7 @@ static const struct snd_soc_dapm_route audio_map[] = { + {"LINE2R", NULL, "Line In"}, + }; + +-/* Logic for a aic3x as connected on a davinci-evm */ ++/* Logic for a tda998x as connected on a davinci-evm */ + static int evm_tda998x_init(struct snd_soc_pcm_runtime *rtd) + { + struct snd_soc_dai *codec_dai = rtd->codec_dai; +@@ -175,6 +175,7 @@ static int evm_tda998x_init(struct snd_soc_pcm_runtime *rtd) + static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) + { + struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct device_node *np = codec->card->dev->of_node; + int ret; +@@ -193,6 +194,11 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + } + ++ /* Divide McASP MCLK by 2 to provide 12MHz to codec */ ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 2); ++ if (ret < 0) ++ return ret; ++ + /* not connected */ + snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); + snd_soc_dapm_disable_pin(dapm, "HPLCOM"); +-- +1.7.9.5 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0003-ASoc-McASP-Lift-Reset-on-CLK-Dividers-when-RX-TX.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0003-ASoc-McASP-Lift-Reset-on-CLK-Dividers-when-RX-TX.patch new file mode 100644 index 00000000..09521a9d --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/audio/0003-ASoc-McASP-Lift-Reset-on-CLK-Dividers-when-RX-TX.patch @@ -0,0 +1,69 @@ +From a01f9e2ead2fcebc3dbb54488f2bc577f5fecd38 Mon Sep 17 00:00:00 2001 +From: Cody Lacey +Date: Fri, 18 Oct 2013 12:42:00 -0500 +Subject: [PATCH 2/2] ASoc: McASP: Lift Reset on CLK Dividers when RX/TX + +If TX/RX CLK or High Frequency TX/RX CLK are set to +output and they use the internally generated clock. +Do not reset the tx/rx clock divider when receiving +or sending data in case they supply the clock source +for another device. +--- + sound/soc/davinci/davinci-mcasp.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c +index 83232c6..7f36228 100644 +--- a/sound/soc/davinci/davinci-mcasp.c ++++ b/sound/soc/davinci/davinci-mcasp.c +@@ -347,6 +347,23 @@ static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val) + + static void mcasp_start_rx(struct davinci_audio_dev *dev) + { ++ u32 pdir = mcasp_get_reg(dev->base + DAVINCI_MCASP_PDIR_REG); ++ u32 thclk_reg = mcasp_get_reg(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG); ++ u32 tclk_reg = mcasp_get_reg(dev->base + DAVINCI_MCASP_ACLKXCTL_REG); ++ ++ /* ++ * If Transmit CLK or High Frequency Transmit CLK are set to output ++ * and they use the internally generated clock. Do not reset the ++ * transmit clock divider when receiving data in case they supply ++ * the clock source for another device. ++ */ ++ if((pdir & ACLKX) && (tclk_reg & ACLKXE)) { ++ mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); ++ } ++ ++ if((pdir & AHCLKX) && (thclk_reg & AHCLKXE)) { ++ mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); ++ } + mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); + mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); + mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); +@@ -364,6 +381,23 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev) + { + u8 offset = 0, i; + u32 cnt; ++ u32 pdir = mcasp_get_reg(dev->base + DAVINCI_MCASP_PDIR_REG); ++ u32 rhclk_reg = mcasp_get_reg(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG); ++ u32 rclk_reg = mcasp_get_reg(dev->base + DAVINCI_MCASP_ACLKRCTL_REG); ++ ++ /* ++ * If Receive CLK or High Frequency Receive CLK are set to output ++ * and they use the internally generated clock. Do not reset the ++ * receive clock divider when transmitting data in case they supply ++ * the clock source for another device. ++ */ ++ if((pdir & ACLKR) && (rclk_reg & ACLKRE)) { ++ mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); ++ } ++ ++ if((pdir & AHCLKR) && (rhclk_reg & AHCLKRE)) { ++ mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); ++ } + + mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); + mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); +-- +1.7.9.5 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/backports/0001-backport-v3.13.7-tpm_i2c_atmel.c.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/backports/0001-backport-v3.13.7-tpm_i2c_atmel.c.patch new file mode 100644 index 00000000..637a3831 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/backports/0001-backport-v3.13.7-tpm_i2c_atmel.c.patch @@ -0,0 +1,4720 @@ +From 3295e0bbcc84baa77c589a012bca5631447801dc Mon Sep 17 00:00:00 2001 +From: Robert Nelson +Date: Tue, 8 Apr 2014 15:50:27 -0500 +Subject: [PATCH] backport (v3.13.7): tpm_i2c_atmel.c + +Signed-off-by: Robert Nelson +--- + drivers/char/tpm/Kconfig | 11 +- + drivers/char/tpm/Makefile | 10 +- + drivers/char/tpm/tpm-interface.c | 1554 +++++++++++++++++++++++++++++++++++ + drivers/char/tpm/tpm.c | 1536 ---------------------------------- + drivers/char/tpm/tpm.h | 57 +- + drivers/char/tpm/tpm_acpi.c | 8 +- + drivers/char/tpm/tpm_atmel.c | 9 +- + drivers/char/tpm/tpm_eventlog.c | 3 - + drivers/char/tpm/tpm_i2c_atmel.c | 284 +++++++ + drivers/char/tpm/tpm_i2c_infineon.c | 195 +++-- + drivers/char/tpm/tpm_ibmvtpm.c | 21 +- + drivers/char/tpm/tpm_nsc.c | 7 +- + drivers/char/tpm/tpm_ppi.c | 41 +- + drivers/char/tpm/tpm_tis.c | 143 ++-- + include/linux/tpm.h | 2 + + 15 files changed, 2172 insertions(+), 1709 deletions(-) + create mode 100644 drivers/char/tpm/tpm-interface.c + delete mode 100644 drivers/char/tpm/tpm.c + create mode 100644 drivers/char/tpm/tpm_i2c_atmel.c + +diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig +index 915875e..1420c5c 100644 +--- a/drivers/char/tpm/Kconfig ++++ b/drivers/char/tpm/Kconfig +@@ -33,6 +33,15 @@ config TCG_TIS + from within Linux. To compile this driver as a module, choose + M here; the module will be called tpm_tis. + ++config TCG_TIS_I2C_ATMEL ++ tristate "TPM Interface Specification 1.2 Interface (I2C - Atmel)" ++ depends on I2C ++ ---help--- ++ If you have an Atmel I2C TPM security chip say Yes and it will be ++ accessible from within Linux. ++ To compile this driver as a module, choose M here; the module will ++ be called tpm_tis_i2c_atmel. ++ + config TCG_TIS_I2C_INFINEON + tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)" + depends on I2C +@@ -42,7 +51,7 @@ config TCG_TIS_I2C_INFINEON + Specification 0.20 say Yes and it will be accessible from within + Linux. + To compile this driver as a module, choose M here; the module +- will be called tpm_tis_i2c_infineon. ++ will be called tpm_i2c_infineon. + + config TCG_NSC + tristate "National Semiconductor TPM Interface" +diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile +index 5b3fc8b..7751499 100644 +--- a/drivers/char/tpm/Makefile ++++ b/drivers/char/tpm/Makefile +@@ -2,16 +2,18 @@ + # Makefile for the kernel tpm device drivers. + # + obj-$(CONFIG_TCG_TPM) += tpm.o ++tpm-y := tpm-interface.o ++tpm-$(CONFIG_ACPI) += tpm_ppi.o ++ + ifdef CONFIG_ACPI +- obj-$(CONFIG_TCG_TPM) += tpm_bios.o +- tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o ++ tpm-y += tpm_eventlog.o tpm_acpi.o + else + ifdef CONFIG_TCG_IBMVTPM +- obj-$(CONFIG_TCG_TPM) += tpm_bios.o +- tpm_bios-objs += tpm_eventlog.o tpm_of.o ++ tpm-y += tpm_eventlog.o tpm_of.o + endif + endif + obj-$(CONFIG_TCG_TIS) += tpm_tis.o ++obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o + obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o + obj-$(CONFIG_TCG_NSC) += tpm_nsc.o + obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o +diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c +new file mode 100644 +index 0000000..6ae41d3 +--- /dev/null ++++ b/drivers/char/tpm/tpm-interface.c +@@ -0,0 +1,1554 @@ ++/* ++ * Copyright (C) 2004 IBM Corporation ++ * ++ * Authors: ++ * Leendert van Doorn ++ * Dave Safford ++ * Reiner Sailer ++ * Kylene Hall ++ * ++ * Maintained by: ++ * ++ * Device driver for TCG/TCPA TPM (trusted platform module). ++ * Specifications at www.trustedcomputinggroup.org ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation, version 2 of the ++ * License. ++ * ++ * Note, the TPM chip is not interrupt driven (only polling) ++ * and can have very long timeouts (minutes!). Hence the unusual ++ * calls to msleep. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "tpm.h" ++#include "tpm_eventlog.h" ++ ++enum tpm_duration { ++ TPM_SHORT = 0, ++ TPM_MEDIUM = 1, ++ TPM_LONG = 2, ++ TPM_UNDEFINED, ++}; ++ ++#define TPM_MAX_ORDINAL 243 ++#define TSC_MAX_ORDINAL 12 ++#define TPM_PROTECTED_COMMAND 0x00 ++#define TPM_CONNECTION_COMMAND 0x40 ++ ++/* ++ * Bug workaround - some TPM's don't flush the most ++ * recently changed pcr on suspend, so force the flush ++ * with an extend to the selected _unused_ non-volatile pcr. ++ */ ++static int tpm_suspend_pcr; ++module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); ++MODULE_PARM_DESC(suspend_pcr, ++ "PCR to use for dummy writes to faciltate flush on suspend."); ++ ++static LIST_HEAD(tpm_chip_list); ++static DEFINE_SPINLOCK(driver_lock); ++static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); ++ ++/* ++ * Array with one entry per ordinal defining the maximum amount ++ * of time the chip could take to return the result. The ordinal ++ * designation of short, medium or long is defined in a table in ++ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The ++ * values of the SHORT, MEDIUM, and LONG durations are retrieved ++ * from the chip during initialization with a call to tpm_get_timeouts. ++ */ ++static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { ++ TPM_UNDEFINED, /* 0 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 5 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 10 */ ++ TPM_SHORT, ++ TPM_MEDIUM, ++ TPM_LONG, ++ TPM_LONG, ++ TPM_MEDIUM, /* 15 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_MEDIUM, ++ TPM_LONG, ++ TPM_SHORT, /* 20 */ ++ TPM_SHORT, ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_SHORT, /* 25 */ ++ TPM_SHORT, ++ TPM_MEDIUM, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_MEDIUM, /* 30 */ ++ TPM_LONG, ++ TPM_MEDIUM, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, /* 35 */ ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_MEDIUM, /* 40 */ ++ TPM_LONG, ++ TPM_MEDIUM, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, /* 45 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_LONG, ++ TPM_MEDIUM, /* 50 */ ++ TPM_MEDIUM, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 55 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_MEDIUM, /* 60 */ ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_MEDIUM, /* 65 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 70 */ ++ TPM_SHORT, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 75 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_LONG, /* 80 */ ++ TPM_UNDEFINED, ++ TPM_MEDIUM, ++ TPM_LONG, ++ TPM_SHORT, ++ TPM_UNDEFINED, /* 85 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 90 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_UNDEFINED, /* 95 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_MEDIUM, /* 100 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 105 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 110 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, /* 115 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_LONG, /* 120 */ ++ TPM_LONG, ++ TPM_MEDIUM, ++ TPM_UNDEFINED, ++ TPM_SHORT, ++ TPM_SHORT, /* 125 */ ++ TPM_SHORT, ++ TPM_LONG, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, /* 130 */ ++ TPM_MEDIUM, ++ TPM_UNDEFINED, ++ TPM_SHORT, ++ TPM_MEDIUM, ++ TPM_UNDEFINED, /* 135 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 140 */ ++ TPM_SHORT, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 145 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 150 */ ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_UNDEFINED, /* 155 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 160 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 165 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_LONG, /* 170 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 175 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_MEDIUM, /* 180 */ ++ TPM_SHORT, ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_MEDIUM, /* 185 */ ++ TPM_SHORT, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 190 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 195 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 200 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, ++ TPM_SHORT, /* 205 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_MEDIUM, /* 210 */ ++ TPM_UNDEFINED, ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_MEDIUM, ++ TPM_UNDEFINED, /* 215 */ ++ TPM_MEDIUM, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, ++ TPM_SHORT, /* 220 */ ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_SHORT, ++ TPM_UNDEFINED, /* 225 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 230 */ ++ TPM_LONG, ++ TPM_MEDIUM, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, /* 235 */ ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_UNDEFINED, ++ TPM_SHORT, /* 240 */ ++ TPM_UNDEFINED, ++ TPM_MEDIUM, ++}; ++ ++static void user_reader_timeout(unsigned long ptr) ++{ ++ struct tpm_chip *chip = (struct tpm_chip *) ptr; ++ ++ schedule_work(&chip->work); ++} ++ ++static void timeout_work(struct work_struct *work) ++{ ++ struct tpm_chip *chip = container_of(work, struct tpm_chip, work); ++ ++ mutex_lock(&chip->buffer_mutex); ++ atomic_set(&chip->data_pending, 0); ++ memset(chip->data_buffer, 0, TPM_BUFSIZE); ++ mutex_unlock(&chip->buffer_mutex); ++} ++ ++/* ++ * Returns max number of jiffies to wait ++ */ ++unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, ++ u32 ordinal) ++{ ++ int duration_idx = TPM_UNDEFINED; ++ int duration = 0; ++ u8 category = (ordinal >> 24) & 0xFF; ++ ++ if ((category == TPM_PROTECTED_COMMAND && ordinal < TPM_MAX_ORDINAL) || ++ (category == TPM_CONNECTION_COMMAND && ordinal < TSC_MAX_ORDINAL)) ++ duration_idx = tpm_ordinal_duration[ordinal]; ++ ++ if (duration_idx != TPM_UNDEFINED) ++ duration = chip->vendor.duration[duration_idx]; ++ if (duration <= 0) ++ return 2 * 60 * HZ; ++ else ++ return duration; ++} ++EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); ++ ++/* ++ * Internal kernel interface to transmit TPM commands ++ */ ++static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, ++ size_t bufsiz) ++{ ++ ssize_t rc; ++ u32 count, ordinal; ++ unsigned long stop; ++ ++ if (bufsiz > TPM_BUFSIZE) ++ bufsiz = TPM_BUFSIZE; ++ ++ count = be32_to_cpu(*((__be32 *) (buf + 2))); ++ ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); ++ if (count == 0) ++ return -ENODATA; ++ if (count > bufsiz) { ++ dev_err(chip->dev, ++ "invalid count value %x %zx\n", count, bufsiz); ++ return -E2BIG; ++ } ++ ++ mutex_lock(&chip->tpm_mutex); ++ ++ rc = chip->vendor.send(chip, (u8 *) buf, count); ++ if (rc < 0) { ++ dev_err(chip->dev, ++ "tpm_transmit: tpm_send: error %zd\n", rc); ++ goto out; ++ } ++ ++ if (chip->vendor.irq) ++ goto out_recv; ++ ++ stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); ++ do { ++ u8 status = chip->vendor.status(chip); ++ if ((status & chip->vendor.req_complete_mask) == ++ chip->vendor.req_complete_val) ++ goto out_recv; ++ ++ if (chip->vendor.req_canceled(chip, status)) { ++ dev_err(chip->dev, "Operation Canceled\n"); ++ rc = -ECANCELED; ++ goto out; ++ } ++ ++ msleep(TPM_TIMEOUT); /* CHECK */ ++ rmb(); ++ } while (time_before(jiffies, stop)); ++ ++ chip->vendor.cancel(chip); ++ dev_err(chip->dev, "Operation Timed out\n"); ++ rc = -ETIME; ++ goto out; ++ ++out_recv: ++ rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz); ++ if (rc < 0) ++ dev_err(chip->dev, ++ "tpm_transmit: tpm_recv: error %zd\n", rc); ++out: ++ mutex_unlock(&chip->tpm_mutex); ++ return rc; ++} ++ ++#define TPM_DIGEST_SIZE 20 ++#define TPM_RET_CODE_IDX 6 ++ ++enum tpm_capabilities { ++ TPM_CAP_FLAG = cpu_to_be32(4), ++ TPM_CAP_PROP = cpu_to_be32(5), ++ CAP_VERSION_1_1 = cpu_to_be32(0x06), ++ CAP_VERSION_1_2 = cpu_to_be32(0x1A) ++}; ++ ++enum tpm_sub_capabilities { ++ TPM_CAP_PROP_PCR = cpu_to_be32(0x101), ++ TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103), ++ TPM_CAP_FLAG_PERM = cpu_to_be32(0x108), ++ TPM_CAP_FLAG_VOL = cpu_to_be32(0x109), ++ TPM_CAP_PROP_OWNER = cpu_to_be32(0x111), ++ TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), ++ TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), ++ ++}; ++ ++static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, ++ int len, const char *desc) ++{ ++ int err; ++ ++ len = tpm_transmit(chip, (u8 *) cmd, len); ++ if (len < 0) ++ return len; ++ else if (len < TPM_HEADER_SIZE) ++ return -EFAULT; ++ ++ err = be32_to_cpu(cmd->header.out.return_code); ++ if (err != 0 && desc) ++ dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); ++ ++ return err; ++} ++ ++#define TPM_INTERNAL_RESULT_SIZE 200 ++#define TPM_TAG_RQU_COMMAND cpu_to_be16(193) ++#define TPM_ORD_GET_CAP cpu_to_be32(101) ++#define TPM_ORD_GET_RANDOM cpu_to_be32(70) ++ ++static const struct tpm_input_header tpm_getcap_header = { ++ .tag = TPM_TAG_RQU_COMMAND, ++ .length = cpu_to_be32(22), ++ .ordinal = TPM_ORD_GET_CAP ++}; ++ ++ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, ++ const char *desc) ++{ ++ struct tpm_cmd_t tpm_cmd; ++ int rc; ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ tpm_cmd.header.in = tpm_getcap_header; ++ if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) { ++ tpm_cmd.params.getcap_in.cap = subcap_id; ++ /*subcap field not necessary */ ++ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0); ++ tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32)); ++ } else { ++ if (subcap_id == TPM_CAP_FLAG_PERM || ++ subcap_id == TPM_CAP_FLAG_VOL) ++ tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG; ++ else ++ tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; ++ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); ++ tpm_cmd.params.getcap_in.subcap = subcap_id; ++ } ++ rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); ++ if (!rc) ++ *cap = tpm_cmd.params.getcap_out.cap; ++ return rc; ++} ++ ++void tpm_gen_interrupt(struct tpm_chip *chip) ++{ ++ struct tpm_cmd_t tpm_cmd; ++ ssize_t rc; ++ ++ tpm_cmd.header.in = tpm_getcap_header; ++ tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; ++ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); ++ tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; ++ ++ rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, ++ "attempting to determine the timeouts"); ++} ++EXPORT_SYMBOL_GPL(tpm_gen_interrupt); ++ ++#define TPM_ORD_STARTUP cpu_to_be32(153) ++#define TPM_ST_CLEAR cpu_to_be16(1) ++#define TPM_ST_STATE cpu_to_be16(2) ++#define TPM_ST_DEACTIVATED cpu_to_be16(3) ++static const struct tpm_input_header tpm_startup_header = { ++ .tag = TPM_TAG_RQU_COMMAND, ++ .length = cpu_to_be32(12), ++ .ordinal = TPM_ORD_STARTUP ++}; ++ ++static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) ++{ ++ struct tpm_cmd_t start_cmd; ++ start_cmd.header.in = tpm_startup_header; ++ start_cmd.params.startup_in.startup_type = startup_type; ++ return transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, ++ "attempting to start the TPM"); ++} ++ ++int tpm_get_timeouts(struct tpm_chip *chip) ++{ ++ struct tpm_cmd_t tpm_cmd; ++ struct timeout_t *timeout_cap; ++ struct duration_t *duration_cap; ++ ssize_t rc; ++ u32 timeout; ++ unsigned int scale = 1; ++ ++ tpm_cmd.header.in = tpm_getcap_header; ++ tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; ++ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); ++ tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; ++ rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL); ++ ++ if (rc == TPM_ERR_INVALID_POSTINIT) { ++ /* The TPM is not started, we are the first to talk to it. ++ Execute a startup command. */ ++ dev_info(chip->dev, "Issuing TPM_STARTUP"); ++ if (tpm_startup(chip, TPM_ST_CLEAR)) ++ return rc; ++ ++ tpm_cmd.header.in = tpm_getcap_header; ++ tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; ++ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); ++ tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; ++ rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, ++ NULL); ++ } ++ if (rc) { ++ dev_err(chip->dev, ++ "A TPM error (%zd) occurred attempting to determine the timeouts\n", ++ rc); ++ goto duration; ++ } ++ ++ if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || ++ be32_to_cpu(tpm_cmd.header.out.length) ++ != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) ++ return -EINVAL; ++ ++ timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; ++ /* Don't overwrite default if value is 0 */ ++ timeout = be32_to_cpu(timeout_cap->a); ++ if (timeout && timeout < 1000) { ++ /* timeouts in msec rather usec */ ++ scale = 1000; ++ chip->vendor.timeout_adjusted = true; ++ } ++ if (timeout) ++ chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale); ++ timeout = be32_to_cpu(timeout_cap->b); ++ if (timeout) ++ chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale); ++ timeout = be32_to_cpu(timeout_cap->c); ++ if (timeout) ++ chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale); ++ timeout = be32_to_cpu(timeout_cap->d); ++ if (timeout) ++ chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale); ++ ++duration: ++ tpm_cmd.header.in = tpm_getcap_header; ++ tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; ++ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); ++ tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; ++ ++ rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, ++ "attempting to determine the durations"); ++ if (rc) ++ return rc; ++ ++ if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || ++ be32_to_cpu(tpm_cmd.header.out.length) ++ != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) ++ return -EINVAL; ++ ++ duration_cap = &tpm_cmd.params.getcap_out.cap.duration; ++ chip->vendor.duration[TPM_SHORT] = ++ usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); ++ chip->vendor.duration[TPM_MEDIUM] = ++ usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); ++ chip->vendor.duration[TPM_LONG] = ++ usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); ++ ++ /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above ++ * value wrong and apparently reports msecs rather than usecs. So we ++ * fix up the resulting too-small TPM_SHORT value to make things work. ++ * We also scale the TPM_MEDIUM and -_LONG values by 1000. ++ */ ++ if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) { ++ chip->vendor.duration[TPM_SHORT] = HZ; ++ chip->vendor.duration[TPM_MEDIUM] *= 1000; ++ chip->vendor.duration[TPM_LONG] *= 1000; ++ chip->vendor.duration_adjusted = true; ++ dev_info(chip->dev, "Adjusting TPM timeout parameters."); ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(tpm_get_timeouts); ++ ++#define TPM_ORD_CONTINUE_SELFTEST 83 ++#define CONTINUE_SELFTEST_RESULT_SIZE 10 ++ ++static struct tpm_input_header continue_selftest_header = { ++ .tag = TPM_TAG_RQU_COMMAND, ++ .length = cpu_to_be32(10), ++ .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), ++}; ++ ++/** ++ * tpm_continue_selftest -- run TPM's selftest ++ * @chip: TPM chip to use ++ * ++ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing ++ * a TPM error code. ++ */ ++static int tpm_continue_selftest(struct tpm_chip *chip) ++{ ++ int rc; ++ struct tpm_cmd_t cmd; ++ ++ cmd.header.in = continue_selftest_header; ++ rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, ++ "continue selftest"); ++ return rc; ++} ++ ++ssize_t tpm_show_enabled(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ cap_t cap; ++ ssize_t rc; ++ ++ rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, ++ "attempting to determine the permanent enabled state"); ++ if (rc) ++ return 0; ++ ++ rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_show_enabled); ++ ++ssize_t tpm_show_active(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ cap_t cap; ++ ssize_t rc; ++ ++ rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, ++ "attempting to determine the permanent active state"); ++ if (rc) ++ return 0; ++ ++ rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_show_active); ++ ++ssize_t tpm_show_owned(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ cap_t cap; ++ ssize_t rc; ++ ++ rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap, ++ "attempting to determine the owner state"); ++ if (rc) ++ return 0; ++ ++ rc = sprintf(buf, "%d\n", cap.owned); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_show_owned); ++ ++ssize_t tpm_show_temp_deactivated(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ cap_t cap; ++ ssize_t rc; ++ ++ rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap, ++ "attempting to determine the temporary state"); ++ if (rc) ++ return 0; ++ ++ rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); ++ ++/* ++ * tpm_chip_find_get - return tpm_chip for given chip number ++ */ ++static struct tpm_chip *tpm_chip_find_get(int chip_num) ++{ ++ struct tpm_chip *pos, *chip = NULL; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(pos, &tpm_chip_list, list) { ++ if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) ++ continue; ++ ++ if (try_module_get(pos->dev->driver->owner)) { ++ chip = pos; ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ return chip; ++} ++ ++#define TPM_ORDINAL_PCRREAD cpu_to_be32(21) ++#define READ_PCR_RESULT_SIZE 30 ++static struct tpm_input_header pcrread_header = { ++ .tag = TPM_TAG_RQU_COMMAND, ++ .length = cpu_to_be32(14), ++ .ordinal = TPM_ORDINAL_PCRREAD ++}; ++ ++static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) ++{ ++ int rc; ++ struct tpm_cmd_t cmd; ++ ++ cmd.header.in = pcrread_header; ++ cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); ++ rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, ++ "attempting to read a pcr value"); ++ ++ if (rc == 0) ++ memcpy(res_buf, cmd.params.pcrread_out.pcr_result, ++ TPM_DIGEST_SIZE); ++ return rc; ++} ++ ++/** ++ * tpm_pcr_read - read a pcr value ++ * @chip_num: tpm idx # or ANY ++ * @pcr_idx: pcr idx to retrieve ++ * @res_buf: TPM_PCR value ++ * size of res_buf is 20 bytes (or NULL if you don't care) ++ * ++ * The TPM driver should be built-in, but for whatever reason it ++ * isn't, protect against the chip disappearing, by incrementing ++ * the module usage count. ++ */ ++int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) ++{ ++ struct tpm_chip *chip; ++ int rc; ++ ++ chip = tpm_chip_find_get(chip_num); ++ if (chip == NULL) ++ return -ENODEV; ++ rc = __tpm_pcr_read(chip, pcr_idx, res_buf); ++ tpm_chip_put(chip); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_pcr_read); ++ ++/** ++ * tpm_pcr_extend - extend pcr value with hash ++ * @chip_num: tpm idx # or AN& ++ * @pcr_idx: pcr idx to extend ++ * @hash: hash value used to extend pcr value ++ * ++ * The TPM driver should be built-in, but for whatever reason it ++ * isn't, protect against the chip disappearing, by incrementing ++ * the module usage count. ++ */ ++#define TPM_ORD_PCR_EXTEND cpu_to_be32(20) ++#define EXTEND_PCR_RESULT_SIZE 34 ++static struct tpm_input_header pcrextend_header = { ++ .tag = TPM_TAG_RQU_COMMAND, ++ .length = cpu_to_be32(34), ++ .ordinal = TPM_ORD_PCR_EXTEND ++}; ++ ++int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) ++{ ++ struct tpm_cmd_t cmd; ++ int rc; ++ struct tpm_chip *chip; ++ ++ chip = tpm_chip_find_get(chip_num); ++ if (chip == NULL) ++ return -ENODEV; ++ ++ cmd.header.in = pcrextend_header; ++ cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); ++ memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); ++ rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, ++ "attempting extend a PCR value"); ++ ++ tpm_chip_put(chip); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_pcr_extend); ++ ++/** ++ * tpm_do_selftest - have the TPM continue its selftest and wait until it ++ * can receive further commands ++ * @chip: TPM chip to use ++ * ++ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing ++ * a TPM error code. ++ */ ++int tpm_do_selftest(struct tpm_chip *chip) ++{ ++ int rc; ++ unsigned int loops; ++ unsigned int delay_msec = 100; ++ unsigned long duration; ++ struct tpm_cmd_t cmd; ++ ++ duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); ++ ++ loops = jiffies_to_msecs(duration) / delay_msec; ++ ++ rc = tpm_continue_selftest(chip); ++ /* This may fail if there was no TPM driver during a suspend/resume ++ * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) ++ */ ++ if (rc) ++ return rc; ++ ++ do { ++ /* Attempt to read a PCR value */ ++ cmd.header.in = pcrread_header; ++ cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); ++ rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); ++ /* Some buggy TPMs will not respond to tpm_tis_ready() for ++ * around 300ms while the self test is ongoing, keep trying ++ * until the self test duration expires. */ ++ if (rc == -ETIME) { ++ dev_info(chip->dev, HW_ERR "TPM command timed out during continue self test"); ++ msleep(delay_msec); ++ continue; ++ } ++ ++ if (rc < TPM_HEADER_SIZE) ++ return -EFAULT; ++ ++ rc = be32_to_cpu(cmd.header.out.return_code); ++ if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { ++ dev_info(chip->dev, ++ "TPM is disabled/deactivated (0x%X)\n", rc); ++ /* TPM is disabled and/or deactivated; driver can ++ * proceed and TPM does handle commands for ++ * suspend/resume correctly ++ */ ++ return 0; ++ } ++ if (rc != TPM_WARN_DOING_SELFTEST) ++ return rc; ++ msleep(delay_msec); ++ } while (--loops > 0); ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_do_selftest); ++ ++int tpm_send(u32 chip_num, void *cmd, size_t buflen) ++{ ++ struct tpm_chip *chip; ++ int rc; ++ ++ chip = tpm_chip_find_get(chip_num); ++ if (chip == NULL) ++ return -ENODEV; ++ ++ rc = transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd"); ++ ++ tpm_chip_put(chip); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_send); ++ ++ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ cap_t cap; ++ u8 digest[TPM_DIGEST_SIZE]; ++ ssize_t rc; ++ int i, j, num_pcrs; ++ char *str = buf; ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, ++ "attempting to determine the number of PCRS"); ++ if (rc) ++ return 0; ++ ++ num_pcrs = be32_to_cpu(cap.num_pcrs); ++ for (i = 0; i < num_pcrs; i++) { ++ rc = __tpm_pcr_read(chip, i, digest); ++ if (rc) ++ break; ++ str += sprintf(str, "PCR-%02d: ", i); ++ for (j = 0; j < TPM_DIGEST_SIZE; j++) ++ str += sprintf(str, "%02X ", digest[j]); ++ str += sprintf(str, "\n"); ++ } ++ return str - buf; ++} ++EXPORT_SYMBOL_GPL(tpm_show_pcrs); ++ ++#define READ_PUBEK_RESULT_SIZE 314 ++#define TPM_ORD_READPUBEK cpu_to_be32(124) ++static struct tpm_input_header tpm_readpubek_header = { ++ .tag = TPM_TAG_RQU_COMMAND, ++ .length = cpu_to_be32(30), ++ .ordinal = TPM_ORD_READPUBEK ++}; ++ ++ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ u8 *data; ++ struct tpm_cmd_t tpm_cmd; ++ ssize_t err; ++ int i, rc; ++ char *str = buf; ++ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ tpm_cmd.header.in = tpm_readpubek_header; ++ err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, ++ "attempting to read the PUBEK"); ++ if (err) ++ goto out; ++ ++ /* ++ ignore header 10 bytes ++ algorithm 32 bits (1 == RSA ) ++ encscheme 16 bits ++ sigscheme 16 bits ++ parameters (RSA 12->bytes: keybit, #primes, expbit) ++ keylenbytes 32 bits ++ 256 byte modulus ++ ignore checksum 20 bytes ++ */ ++ data = tpm_cmd.params.readpubek_out_buffer; ++ str += ++ sprintf(str, ++ "Algorithm: %02X %02X %02X %02X\n" ++ "Encscheme: %02X %02X\n" ++ "Sigscheme: %02X %02X\n" ++ "Parameters: %02X %02X %02X %02X " ++ "%02X %02X %02X %02X " ++ "%02X %02X %02X %02X\n" ++ "Modulus length: %d\n" ++ "Modulus:\n", ++ data[0], data[1], data[2], data[3], ++ data[4], data[5], ++ data[6], data[7], ++ data[12], data[13], data[14], data[15], ++ data[16], data[17], data[18], data[19], ++ data[20], data[21], data[22], data[23], ++ be32_to_cpu(*((__be32 *) (data + 24)))); ++ ++ for (i = 0; i < 256; i++) { ++ str += sprintf(str, "%02X ", data[i + 28]); ++ if ((i + 1) % 16 == 0) ++ str += sprintf(str, "\n"); ++ } ++out: ++ rc = str - buf; ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_show_pubek); ++ ++ ++ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ cap_t cap; ++ ssize_t rc; ++ char *str = buf; ++ ++ rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, ++ "attempting to determine the manufacturer"); ++ if (rc) ++ return 0; ++ str += sprintf(str, "Manufacturer: 0x%x\n", ++ be32_to_cpu(cap.manufacturer_id)); ++ ++ /* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */ ++ rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap, ++ "attempting to determine the 1.2 version"); ++ if (!rc) { ++ str += sprintf(str, ++ "TCG version: %d.%d\nFirmware version: %d.%d\n", ++ cap.tpm_version_1_2.Major, ++ cap.tpm_version_1_2.Minor, ++ cap.tpm_version_1_2.revMajor, ++ cap.tpm_version_1_2.revMinor); ++ } else { ++ /* Otherwise just use TPM_STRUCT_VER */ ++ rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap, ++ "attempting to determine the 1.1 version"); ++ if (rc) ++ return 0; ++ str += sprintf(str, ++ "TCG version: %d.%d\nFirmware version: %d.%d\n", ++ cap.tpm_version.Major, ++ cap.tpm_version.Minor, ++ cap.tpm_version.revMajor, ++ cap.tpm_version.revMinor); ++ } ++ ++ return str - buf; ++} ++EXPORT_SYMBOL_GPL(tpm_show_caps); ++ ++ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ if (chip->vendor.duration[TPM_LONG] == 0) ++ return 0; ++ ++ return sprintf(buf, "%d %d %d [%s]\n", ++ jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]), ++ jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]), ++ jiffies_to_usecs(chip->vendor.duration[TPM_LONG]), ++ chip->vendor.duration_adjusted ++ ? "adjusted" : "original"); ++} ++EXPORT_SYMBOL_GPL(tpm_show_durations); ++ ++ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%d %d %d %d [%s]\n", ++ jiffies_to_usecs(chip->vendor.timeout_a), ++ jiffies_to_usecs(chip->vendor.timeout_b), ++ jiffies_to_usecs(chip->vendor.timeout_c), ++ jiffies_to_usecs(chip->vendor.timeout_d), ++ chip->vendor.timeout_adjusted ++ ? "adjusted" : "original"); ++} ++EXPORT_SYMBOL_GPL(tpm_show_timeouts); ++ ++ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ if (chip == NULL) ++ return 0; ++ ++ chip->vendor.cancel(chip); ++ return count; ++} ++EXPORT_SYMBOL_GPL(tpm_store_cancel); ++ ++static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, ++ bool check_cancel, bool *canceled) ++{ ++ u8 status = chip->vendor.status(chip); ++ ++ *canceled = false; ++ if ((status & mask) == mask) ++ return true; ++ if (check_cancel && chip->vendor.req_canceled(chip, status)) { ++ *canceled = true; ++ return true; ++ } ++ return false; ++} ++ ++int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, ++ wait_queue_head_t *queue, bool check_cancel) ++{ ++ unsigned long stop; ++ long rc; ++ u8 status; ++ bool canceled = false; ++ ++ /* check current status */ ++ status = chip->vendor.status(chip); ++ if ((status & mask) == mask) ++ return 0; ++ ++ stop = jiffies + timeout; ++ ++ if (chip->vendor.irq) { ++again: ++ timeout = stop - jiffies; ++ if ((long)timeout <= 0) ++ return -ETIME; ++ rc = wait_event_interruptible_timeout(*queue, ++ wait_for_tpm_stat_cond(chip, mask, check_cancel, ++ &canceled), ++ timeout); ++ if (rc > 0) { ++ if (canceled) ++ return -ECANCELED; ++ return 0; ++ } ++ if (rc == -ERESTARTSYS && freezing(current)) { ++ clear_thread_flag(TIF_SIGPENDING); ++ goto again; ++ } ++ } else { ++ do { ++ msleep(TPM_TIMEOUT); ++ status = chip->vendor.status(chip); ++ if ((status & mask) == mask) ++ return 0; ++ } while (time_before(jiffies, stop)); ++ } ++ return -ETIME; ++} ++EXPORT_SYMBOL_GPL(wait_for_tpm_stat); ++/* ++ * Device file system interface to the TPM ++ * ++ * It's assured that the chip will be opened just once, ++ * by the check of is_open variable, which is protected ++ * by driver_lock. ++ */ ++int tpm_open(struct inode *inode, struct file *file) ++{ ++ struct miscdevice *misc = file->private_data; ++ struct tpm_chip *chip = container_of(misc, struct tpm_chip, ++ vendor.miscdev); ++ ++ if (test_and_set_bit(0, &chip->is_open)) { ++ dev_dbg(chip->dev, "Another process owns this TPM\n"); ++ return -EBUSY; ++ } ++ ++ chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL); ++ if (chip->data_buffer == NULL) { ++ clear_bit(0, &chip->is_open); ++ return -ENOMEM; ++ } ++ ++ atomic_set(&chip->data_pending, 0); ++ ++ file->private_data = chip; ++ get_device(chip->dev); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(tpm_open); ++ ++/* ++ * Called on file close ++ */ ++int tpm_release(struct inode *inode, struct file *file) ++{ ++ struct tpm_chip *chip = file->private_data; ++ ++ del_singleshot_timer_sync(&chip->user_read_timer); ++ flush_work(&chip->work); ++ file->private_data = NULL; ++ atomic_set(&chip->data_pending, 0); ++ kzfree(chip->data_buffer); ++ clear_bit(0, &chip->is_open); ++ put_device(chip->dev); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(tpm_release); ++ ++ssize_t tpm_write(struct file *file, const char __user *buf, ++ size_t size, loff_t *off) ++{ ++ struct tpm_chip *chip = file->private_data; ++ size_t in_size = size; ++ ssize_t out_size; ++ ++ /* cannot perform a write until the read has cleared ++ either via tpm_read or a user_read_timer timeout. ++ This also prevents splitted buffered writes from blocking here. ++ */ ++ if (atomic_read(&chip->data_pending) != 0) ++ return -EBUSY; ++ ++ if (in_size > TPM_BUFSIZE) ++ return -E2BIG; ++ ++ mutex_lock(&chip->buffer_mutex); ++ ++ if (copy_from_user ++ (chip->data_buffer, (void __user *) buf, in_size)) { ++ mutex_unlock(&chip->buffer_mutex); ++ return -EFAULT; ++ } ++ ++ /* atomic tpm command send and result receive */ ++ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); ++ if (out_size < 0) { ++ mutex_unlock(&chip->buffer_mutex); ++ return out_size; ++ } ++ ++ atomic_set(&chip->data_pending, out_size); ++ mutex_unlock(&chip->buffer_mutex); ++ ++ /* Set a timeout by which the reader must come claim the result */ ++ mod_timer(&chip->user_read_timer, jiffies + (60 * HZ)); ++ ++ return in_size; ++} ++EXPORT_SYMBOL_GPL(tpm_write); ++ ++ssize_t tpm_read(struct file *file, char __user *buf, ++ size_t size, loff_t *off) ++{ ++ struct tpm_chip *chip = file->private_data; ++ ssize_t ret_size; ++ int rc; ++ ++ del_singleshot_timer_sync(&chip->user_read_timer); ++ flush_work(&chip->work); ++ ret_size = atomic_read(&chip->data_pending); ++ if (ret_size > 0) { /* relay data */ ++ ssize_t orig_ret_size = ret_size; ++ if (size < ret_size) ++ ret_size = size; ++ ++ mutex_lock(&chip->buffer_mutex); ++ rc = copy_to_user(buf, chip->data_buffer, ret_size); ++ memset(chip->data_buffer, 0, orig_ret_size); ++ if (rc) ++ ret_size = -EFAULT; ++ ++ mutex_unlock(&chip->buffer_mutex); ++ } ++ ++ atomic_set(&chip->data_pending, 0); ++ ++ return ret_size; ++} ++EXPORT_SYMBOL_GPL(tpm_read); ++ ++void tpm_remove_hardware(struct device *dev) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ if (chip == NULL) { ++ dev_err(dev, "No device data found\n"); ++ return; ++ } ++ ++ spin_lock(&driver_lock); ++ list_del_rcu(&chip->list); ++ spin_unlock(&driver_lock); ++ synchronize_rcu(); ++ ++ misc_deregister(&chip->vendor.miscdev); ++ sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); ++ tpm_remove_ppi(&dev->kobj); ++ tpm_bios_log_teardown(chip->bios_dir); ++ ++ /* write it this way to be explicit (chip->dev == dev) */ ++ put_device(chip->dev); ++} ++EXPORT_SYMBOL_GPL(tpm_remove_hardware); ++ ++#define TPM_ORD_SAVESTATE cpu_to_be32(152) ++#define SAVESTATE_RESULT_SIZE 10 ++ ++static struct tpm_input_header savestate_header = { ++ .tag = TPM_TAG_RQU_COMMAND, ++ .length = cpu_to_be32(10), ++ .ordinal = TPM_ORD_SAVESTATE ++}; ++ ++/* ++ * We are about to suspend. Save the TPM state ++ * so that it can be restored. ++ */ ++int tpm_pm_suspend(struct device *dev) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ struct tpm_cmd_t cmd; ++ int rc, try; ++ ++ u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; ++ ++ if (chip == NULL) ++ return -ENODEV; ++ ++ /* for buggy tpm, flush pcrs with extend to selected dummy */ ++ if (tpm_suspend_pcr) { ++ cmd.header.in = pcrextend_header; ++ cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); ++ memcpy(cmd.params.pcrextend_in.hash, dummy_hash, ++ TPM_DIGEST_SIZE); ++ rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, ++ "extending dummy pcr before suspend"); ++ } ++ ++ /* now do the actual savestate */ ++ for (try = 0; try < TPM_RETRY; try++) { ++ cmd.header.in = savestate_header; ++ rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL); ++ ++ /* ++ * If the TPM indicates that it is too busy to respond to ++ * this command then retry before giving up. It can take ++ * several seconds for this TPM to be ready. ++ * ++ * This can happen if the TPM has already been sent the ++ * SaveState command before the driver has loaded. TCG 1.2 ++ * specification states that any communication after SaveState ++ * may cause the TPM to invalidate previously saved state. ++ */ ++ if (rc != TPM_WARN_RETRY) ++ break; ++ msleep(TPM_TIMEOUT_RETRY); ++ } ++ ++ if (rc) ++ dev_err(chip->dev, ++ "Error (%d) sending savestate before suspend\n", rc); ++ else if (try > 0) ++ dev_warn(chip->dev, "TPM savestate took %dms\n", ++ try * TPM_TIMEOUT_RETRY); ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(tpm_pm_suspend); ++ ++/* ++ * Resume from a power safe. The BIOS already restored ++ * the TPM state. ++ */ ++int tpm_pm_resume(struct device *dev) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ if (chip == NULL) ++ return -ENODEV; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(tpm_pm_resume); ++ ++#define TPM_GETRANDOM_RESULT_SIZE 18 ++static struct tpm_input_header tpm_getrandom_header = { ++ .tag = TPM_TAG_RQU_COMMAND, ++ .length = cpu_to_be32(14), ++ .ordinal = TPM_ORD_GET_RANDOM ++}; ++ ++/** ++ * tpm_get_random() - Get random bytes from the tpm's RNG ++ * @chip_num: A specific chip number for the request or TPM_ANY_NUM ++ * @out: destination buffer for the random bytes ++ * @max: the max number of bytes to write to @out ++ * ++ * Returns < 0 on error and the number of bytes read on success ++ */ ++int tpm_get_random(u32 chip_num, u8 *out, size_t max) ++{ ++ struct tpm_chip *chip; ++ struct tpm_cmd_t tpm_cmd; ++ u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA); ++ int err, total = 0, retries = 5; ++ u8 *dest = out; ++ ++ chip = tpm_chip_find_get(chip_num); ++ if (chip == NULL) ++ return -ENODEV; ++ ++ if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) ++ return -EINVAL; ++ ++ do { ++ tpm_cmd.header.in = tpm_getrandom_header; ++ tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); ++ ++ err = transmit_cmd(chip, &tpm_cmd, ++ TPM_GETRANDOM_RESULT_SIZE + num_bytes, ++ "attempting get random"); ++ if (err) ++ break; ++ ++ recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); ++ memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd); ++ ++ dest += recd; ++ total += recd; ++ num_bytes -= recd; ++ } while (retries-- && total < max); ++ ++ return total ? total : -EIO; ++} ++EXPORT_SYMBOL_GPL(tpm_get_random); ++ ++/* In case vendor provided release function, call it too.*/ ++ ++void tpm_dev_vendor_release(struct tpm_chip *chip) ++{ ++ if (!chip) ++ return; ++ ++ if (chip->vendor.release) ++ chip->vendor.release(chip->dev); ++ ++ clear_bit(chip->dev_num, dev_mask); ++} ++EXPORT_SYMBOL_GPL(tpm_dev_vendor_release); ++ ++ ++/* ++ * Once all references to platform device are down to 0, ++ * release all allocated structures. ++ */ ++void tpm_dev_release(struct device *dev) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ if (!chip) ++ return; ++ ++ tpm_dev_vendor_release(chip); ++ ++ chip->release(dev); ++ kfree(chip); ++} ++EXPORT_SYMBOL_GPL(tpm_dev_release); ++ ++/* ++ * Called from tpm_.c probe function only for devices ++ * the driver has determined it should claim. Prior to calling ++ * this function the specific probe function has called pci_enable_device ++ * upon errant exit from this function specific probe function should call ++ * pci_disable_device ++ */ ++struct tpm_chip *tpm_register_hardware(struct device *dev, ++ const struct tpm_vendor_specific *entry) ++{ ++ struct tpm_chip *chip; ++ ++ /* Driver specific per-device data */ ++ chip = kzalloc(sizeof(*chip), GFP_KERNEL); ++ ++ if (chip == NULL) ++ return NULL; ++ ++ mutex_init(&chip->buffer_mutex); ++ mutex_init(&chip->tpm_mutex); ++ INIT_LIST_HEAD(&chip->list); ++ ++ INIT_WORK(&chip->work, timeout_work); ++ ++ setup_timer(&chip->user_read_timer, user_reader_timeout, ++ (unsigned long)chip); ++ ++ memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); ++ ++ chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); ++ ++ if (chip->dev_num >= TPM_NUM_DEVICES) { ++ dev_err(dev, "No available tpm device numbers\n"); ++ goto out_free; ++ } else if (chip->dev_num == 0) ++ chip->vendor.miscdev.minor = TPM_MINOR; ++ else ++ chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; ++ ++ set_bit(chip->dev_num, dev_mask); ++ ++ scnprintf(chip->devname, sizeof(chip->devname), "%s%d", "tpm", ++ chip->dev_num); ++ chip->vendor.miscdev.name = chip->devname; ++ ++ chip->vendor.miscdev.parent = dev; ++ chip->dev = get_device(dev); ++ chip->release = dev->release; ++ dev->release = tpm_dev_release; ++ dev_set_drvdata(dev, chip); ++ ++ if (misc_register(&chip->vendor.miscdev)) { ++ dev_err(chip->dev, ++ "unable to misc_register %s, minor %d\n", ++ chip->vendor.miscdev.name, ++ chip->vendor.miscdev.minor); ++ goto put_device; ++ } ++ ++ if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { ++ misc_deregister(&chip->vendor.miscdev); ++ goto put_device; ++ } ++ ++ if (tpm_add_ppi(&dev->kobj)) { ++ misc_deregister(&chip->vendor.miscdev); ++ goto put_device; ++ } ++ ++ chip->bios_dir = tpm_bios_log_setup(chip->devname); ++ ++ /* Make chip available */ ++ spin_lock(&driver_lock); ++ list_add_rcu(&chip->list, &tpm_chip_list); ++ spin_unlock(&driver_lock); ++ ++ return chip; ++ ++put_device: ++ put_device(chip->dev); ++out_free: ++ kfree(chip); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(tpm_register_hardware); ++ ++MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); ++MODULE_DESCRIPTION("TPM Driver"); ++MODULE_VERSION("2.0"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c +deleted file mode 100644 +index ba780b7..0000000 +--- a/drivers/char/tpm/tpm.c ++++ /dev/null +@@ -1,1536 +0,0 @@ +-/* +- * Copyright (C) 2004 IBM Corporation +- * +- * Authors: +- * Leendert van Doorn +- * Dave Safford +- * Reiner Sailer +- * Kylene Hall +- * +- * Maintained by: +- * +- * Device driver for TCG/TCPA TPM (trusted platform module). +- * Specifications at www.trustedcomputinggroup.org +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License as +- * published by the Free Software Foundation, version 2 of the +- * License. +- * +- * Note, the TPM chip is not interrupt driven (only polling) +- * and can have very long timeouts (minutes!). Hence the unusual +- * calls to msleep. +- * +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "tpm.h" +-#include "tpm_eventlog.h" +- +-enum tpm_duration { +- TPM_SHORT = 0, +- TPM_MEDIUM = 1, +- TPM_LONG = 2, +- TPM_UNDEFINED, +-}; +- +-#define TPM_MAX_ORDINAL 243 +-#define TPM_MAX_PROTECTED_ORDINAL 12 +-#define TPM_PROTECTED_ORDINAL_MASK 0xFF +- +-/* +- * Bug workaround - some TPM's don't flush the most +- * recently changed pcr on suspend, so force the flush +- * with an extend to the selected _unused_ non-volatile pcr. +- */ +-static int tpm_suspend_pcr; +-module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); +-MODULE_PARM_DESC(suspend_pcr, +- "PCR to use for dummy writes to faciltate flush on suspend."); +- +-static LIST_HEAD(tpm_chip_list); +-static DEFINE_SPINLOCK(driver_lock); +-static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); +- +-/* +- * Array with one entry per ordinal defining the maximum amount +- * of time the chip could take to return the result. The ordinal +- * designation of short, medium or long is defined in a table in +- * TCG Specification TPM Main Part 2 TPM Structures Section 17. The +- * values of the SHORT, MEDIUM, and LONG durations are retrieved +- * from the chip during initialization with a call to tpm_get_timeouts. +- */ +-static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { +- TPM_UNDEFINED, /* 0 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 5 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 10 */ +- TPM_SHORT, +-}; +- +-static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { +- TPM_UNDEFINED, /* 0 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 5 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 10 */ +- TPM_SHORT, +- TPM_MEDIUM, +- TPM_LONG, +- TPM_LONG, +- TPM_MEDIUM, /* 15 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_MEDIUM, +- TPM_LONG, +- TPM_SHORT, /* 20 */ +- TPM_SHORT, +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_SHORT, /* 25 */ +- TPM_SHORT, +- TPM_MEDIUM, +- TPM_SHORT, +- TPM_SHORT, +- TPM_MEDIUM, /* 30 */ +- TPM_LONG, +- TPM_MEDIUM, +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, /* 35 */ +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_MEDIUM, /* 40 */ +- TPM_LONG, +- TPM_MEDIUM, +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, /* 45 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_LONG, +- TPM_MEDIUM, /* 50 */ +- TPM_MEDIUM, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 55 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_MEDIUM, /* 60 */ +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_SHORT, +- TPM_SHORT, +- TPM_MEDIUM, /* 65 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 70 */ +- TPM_SHORT, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 75 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_LONG, /* 80 */ +- TPM_UNDEFINED, +- TPM_MEDIUM, +- TPM_LONG, +- TPM_SHORT, +- TPM_UNDEFINED, /* 85 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 90 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_UNDEFINED, /* 95 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_MEDIUM, /* 100 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 105 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 110 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, /* 115 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_LONG, /* 120 */ +- TPM_LONG, +- TPM_MEDIUM, +- TPM_UNDEFINED, +- TPM_SHORT, +- TPM_SHORT, /* 125 */ +- TPM_SHORT, +- TPM_LONG, +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, /* 130 */ +- TPM_MEDIUM, +- TPM_UNDEFINED, +- TPM_SHORT, +- TPM_MEDIUM, +- TPM_UNDEFINED, /* 135 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 140 */ +- TPM_SHORT, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 145 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 150 */ +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_SHORT, +- TPM_SHORT, +- TPM_UNDEFINED, /* 155 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 160 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 165 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_LONG, /* 170 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 175 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_MEDIUM, /* 180 */ +- TPM_SHORT, +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_MEDIUM, /* 185 */ +- TPM_SHORT, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 190 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 195 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 200 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, +- TPM_SHORT, /* 205 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_MEDIUM, /* 210 */ +- TPM_UNDEFINED, +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_MEDIUM, +- TPM_UNDEFINED, /* 215 */ +- TPM_MEDIUM, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, +- TPM_SHORT, /* 220 */ +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_SHORT, +- TPM_UNDEFINED, /* 225 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 230 */ +- TPM_LONG, +- TPM_MEDIUM, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, /* 235 */ +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_UNDEFINED, +- TPM_SHORT, /* 240 */ +- TPM_UNDEFINED, +- TPM_MEDIUM, +-}; +- +-static void user_reader_timeout(unsigned long ptr) +-{ +- struct tpm_chip *chip = (struct tpm_chip *) ptr; +- +- schedule_work(&chip->work); +-} +- +-static void timeout_work(struct work_struct *work) +-{ +- struct tpm_chip *chip = container_of(work, struct tpm_chip, work); +- +- mutex_lock(&chip->buffer_mutex); +- atomic_set(&chip->data_pending, 0); +- memset(chip->data_buffer, 0, TPM_BUFSIZE); +- mutex_unlock(&chip->buffer_mutex); +-} +- +-/* +- * Returns max number of jiffies to wait +- */ +-unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, +- u32 ordinal) +-{ +- int duration_idx = TPM_UNDEFINED; +- int duration = 0; +- +- if (ordinal < TPM_MAX_ORDINAL) +- duration_idx = tpm_ordinal_duration[ordinal]; +- else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < +- TPM_MAX_PROTECTED_ORDINAL) +- duration_idx = +- tpm_protected_ordinal_duration[ordinal & +- TPM_PROTECTED_ORDINAL_MASK]; +- +- if (duration_idx != TPM_UNDEFINED) +- duration = chip->vendor.duration[duration_idx]; +- if (duration <= 0) +- return 2 * 60 * HZ; +- else +- return duration; +-} +-EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); +- +-/* +- * Internal kernel interface to transmit TPM commands +- */ +-static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, +- size_t bufsiz) +-{ +- ssize_t rc; +- u32 count, ordinal; +- unsigned long stop; +- +- if (bufsiz > TPM_BUFSIZE) +- bufsiz = TPM_BUFSIZE; +- +- count = be32_to_cpu(*((__be32 *) (buf + 2))); +- ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); +- if (count == 0) +- return -ENODATA; +- if (count > bufsiz) { +- dev_err(chip->dev, +- "invalid count value %x %zx \n", count, bufsiz); +- return -E2BIG; +- } +- +- mutex_lock(&chip->tpm_mutex); +- +- if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { +- dev_err(chip->dev, +- "tpm_transmit: tpm_send: error %zd\n", rc); +- goto out; +- } +- +- if (chip->vendor.irq) +- goto out_recv; +- +- stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); +- do { +- u8 status = chip->vendor.status(chip); +- if ((status & chip->vendor.req_complete_mask) == +- chip->vendor.req_complete_val) +- goto out_recv; +- +- if ((status == chip->vendor.req_canceled)) { +- dev_err(chip->dev, "Operation Canceled\n"); +- rc = -ECANCELED; +- goto out; +- } +- +- msleep(TPM_TIMEOUT); /* CHECK */ +- rmb(); +- } while (time_before(jiffies, stop)); +- +- chip->vendor.cancel(chip); +- dev_err(chip->dev, "Operation Timed out\n"); +- rc = -ETIME; +- goto out; +- +-out_recv: +- rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz); +- if (rc < 0) +- dev_err(chip->dev, +- "tpm_transmit: tpm_recv: error %zd\n", rc); +-out: +- mutex_unlock(&chip->tpm_mutex); +- return rc; +-} +- +-#define TPM_DIGEST_SIZE 20 +-#define TPM_RET_CODE_IDX 6 +- +-enum tpm_capabilities { +- TPM_CAP_FLAG = cpu_to_be32(4), +- TPM_CAP_PROP = cpu_to_be32(5), +- CAP_VERSION_1_1 = cpu_to_be32(0x06), +- CAP_VERSION_1_2 = cpu_to_be32(0x1A) +-}; +- +-enum tpm_sub_capabilities { +- TPM_CAP_PROP_PCR = cpu_to_be32(0x101), +- TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103), +- TPM_CAP_FLAG_PERM = cpu_to_be32(0x108), +- TPM_CAP_FLAG_VOL = cpu_to_be32(0x109), +- TPM_CAP_PROP_OWNER = cpu_to_be32(0x111), +- TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), +- TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), +- +-}; +- +-static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, +- int len, const char *desc) +-{ +- int err; +- +- len = tpm_transmit(chip,(u8 *) cmd, len); +- if (len < 0) +- return len; +- else if (len < TPM_HEADER_SIZE) +- return -EFAULT; +- +- err = be32_to_cpu(cmd->header.out.return_code); +- if (err != 0) +- dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); +- +- return err; +-} +- +-#define TPM_INTERNAL_RESULT_SIZE 200 +-#define TPM_TAG_RQU_COMMAND cpu_to_be16(193) +-#define TPM_ORD_GET_CAP cpu_to_be32(101) +-#define TPM_ORD_GET_RANDOM cpu_to_be32(70) +- +-static const struct tpm_input_header tpm_getcap_header = { +- .tag = TPM_TAG_RQU_COMMAND, +- .length = cpu_to_be32(22), +- .ordinal = TPM_ORD_GET_CAP +-}; +- +-ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, +- const char *desc) +-{ +- struct tpm_cmd_t tpm_cmd; +- int rc; +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- tpm_cmd.header.in = tpm_getcap_header; +- if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) { +- tpm_cmd.params.getcap_in.cap = subcap_id; +- /*subcap field not necessary */ +- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0); +- tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32)); +- } else { +- if (subcap_id == TPM_CAP_FLAG_PERM || +- subcap_id == TPM_CAP_FLAG_VOL) +- tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG; +- else +- tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; +- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); +- tpm_cmd.params.getcap_in.subcap = subcap_id; +- } +- rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); +- if (!rc) +- *cap = tpm_cmd.params.getcap_out.cap; +- return rc; +-} +- +-void tpm_gen_interrupt(struct tpm_chip *chip) +-{ +- struct tpm_cmd_t tpm_cmd; +- ssize_t rc; +- +- tpm_cmd.header.in = tpm_getcap_header; +- tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; +- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); +- tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; +- +- rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, +- "attempting to determine the timeouts"); +-} +-EXPORT_SYMBOL_GPL(tpm_gen_interrupt); +- +-int tpm_get_timeouts(struct tpm_chip *chip) +-{ +- struct tpm_cmd_t tpm_cmd; +- struct timeout_t *timeout_cap; +- struct duration_t *duration_cap; +- ssize_t rc; +- u32 timeout; +- unsigned int scale = 1; +- +- tpm_cmd.header.in = tpm_getcap_header; +- tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; +- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); +- tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; +- +- rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, +- "attempting to determine the timeouts"); +- if (rc) +- goto duration; +- +- if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || +- be32_to_cpu(tpm_cmd.header.out.length) +- != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) +- return -EINVAL; +- +- timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; +- /* Don't overwrite default if value is 0 */ +- timeout = be32_to_cpu(timeout_cap->a); +- if (timeout && timeout < 1000) { +- /* timeouts in msec rather usec */ +- scale = 1000; +- chip->vendor.timeout_adjusted = true; +- } +- if (timeout) +- chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->b); +- if (timeout) +- chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->c); +- if (timeout) +- chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->d); +- if (timeout) +- chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale); +- +-duration: +- tpm_cmd.header.in = tpm_getcap_header; +- tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; +- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); +- tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; +- +- rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, +- "attempting to determine the durations"); +- if (rc) +- return rc; +- +- if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || +- be32_to_cpu(tpm_cmd.header.out.length) +- != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) +- return -EINVAL; +- +- duration_cap = &tpm_cmd.params.getcap_out.cap.duration; +- chip->vendor.duration[TPM_SHORT] = +- usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); +- chip->vendor.duration[TPM_MEDIUM] = +- usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); +- chip->vendor.duration[TPM_LONG] = +- usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); +- +- /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above +- * value wrong and apparently reports msecs rather than usecs. So we +- * fix up the resulting too-small TPM_SHORT value to make things work. +- * We also scale the TPM_MEDIUM and -_LONG values by 1000. +- */ +- if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) { +- chip->vendor.duration[TPM_SHORT] = HZ; +- chip->vendor.duration[TPM_MEDIUM] *= 1000; +- chip->vendor.duration[TPM_LONG] *= 1000; +- chip->vendor.duration_adjusted = true; +- dev_info(chip->dev, "Adjusting TPM timeout parameters."); +- } +- return 0; +-} +-EXPORT_SYMBOL_GPL(tpm_get_timeouts); +- +-#define TPM_ORD_CONTINUE_SELFTEST 83 +-#define CONTINUE_SELFTEST_RESULT_SIZE 10 +- +-static struct tpm_input_header continue_selftest_header = { +- .tag = TPM_TAG_RQU_COMMAND, +- .length = cpu_to_be32(10), +- .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), +-}; +- +-/** +- * tpm_continue_selftest -- run TPM's selftest +- * @chip: TPM chip to use +- * +- * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing +- * a TPM error code. +- */ +-static int tpm_continue_selftest(struct tpm_chip *chip) +-{ +- int rc; +- struct tpm_cmd_t cmd; +- +- cmd.header.in = continue_selftest_header; +- rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, +- "continue selftest"); +- return rc; +-} +- +-ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, +- char *buf) +-{ +- cap_t cap; +- ssize_t rc; +- +- rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, +- "attempting to determine the permanent enabled state"); +- if (rc) +- return 0; +- +- rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_show_enabled); +- +-ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, +- char *buf) +-{ +- cap_t cap; +- ssize_t rc; +- +- rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, +- "attempting to determine the permanent active state"); +- if (rc) +- return 0; +- +- rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_show_active); +- +-ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, +- char *buf) +-{ +- cap_t cap; +- ssize_t rc; +- +- rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap, +- "attempting to determine the owner state"); +- if (rc) +- return 0; +- +- rc = sprintf(buf, "%d\n", cap.owned); +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_show_owned); +- +-ssize_t tpm_show_temp_deactivated(struct device * dev, +- struct device_attribute * attr, char *buf) +-{ +- cap_t cap; +- ssize_t rc; +- +- rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap, +- "attempting to determine the temporary state"); +- if (rc) +- return 0; +- +- rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); +- +-/* +- * tpm_chip_find_get - return tpm_chip for given chip number +- */ +-static struct tpm_chip *tpm_chip_find_get(int chip_num) +-{ +- struct tpm_chip *pos, *chip = NULL; +- +- rcu_read_lock(); +- list_for_each_entry_rcu(pos, &tpm_chip_list, list) { +- if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) +- continue; +- +- if (try_module_get(pos->dev->driver->owner)) { +- chip = pos; +- break; +- } +- } +- rcu_read_unlock(); +- return chip; +-} +- +-#define TPM_ORDINAL_PCRREAD cpu_to_be32(21) +-#define READ_PCR_RESULT_SIZE 30 +-static struct tpm_input_header pcrread_header = { +- .tag = TPM_TAG_RQU_COMMAND, +- .length = cpu_to_be32(14), +- .ordinal = TPM_ORDINAL_PCRREAD +-}; +- +-static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +-{ +- int rc; +- struct tpm_cmd_t cmd; +- +- cmd.header.in = pcrread_header; +- cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); +- rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, +- "attempting to read a pcr value"); +- +- if (rc == 0) +- memcpy(res_buf, cmd.params.pcrread_out.pcr_result, +- TPM_DIGEST_SIZE); +- return rc; +-} +- +-/** +- * tpm_pcr_read - read a pcr value +- * @chip_num: tpm idx # or ANY +- * @pcr_idx: pcr idx to retrieve +- * @res_buf: TPM_PCR value +- * size of res_buf is 20 bytes (or NULL if you don't care) +- * +- * The TPM driver should be built-in, but for whatever reason it +- * isn't, protect against the chip disappearing, by incrementing +- * the module usage count. +- */ +-int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) +-{ +- struct tpm_chip *chip; +- int rc; +- +- chip = tpm_chip_find_get(chip_num); +- if (chip == NULL) +- return -ENODEV; +- rc = __tpm_pcr_read(chip, pcr_idx, res_buf); +- tpm_chip_put(chip); +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_pcr_read); +- +-/** +- * tpm_pcr_extend - extend pcr value with hash +- * @chip_num: tpm idx # or AN& +- * @pcr_idx: pcr idx to extend +- * @hash: hash value used to extend pcr value +- * +- * The TPM driver should be built-in, but for whatever reason it +- * isn't, protect against the chip disappearing, by incrementing +- * the module usage count. +- */ +-#define TPM_ORD_PCR_EXTEND cpu_to_be32(20) +-#define EXTEND_PCR_RESULT_SIZE 34 +-static struct tpm_input_header pcrextend_header = { +- .tag = TPM_TAG_RQU_COMMAND, +- .length = cpu_to_be32(34), +- .ordinal = TPM_ORD_PCR_EXTEND +-}; +- +-int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) +-{ +- struct tpm_cmd_t cmd; +- int rc; +- struct tpm_chip *chip; +- +- chip = tpm_chip_find_get(chip_num); +- if (chip == NULL) +- return -ENODEV; +- +- cmd.header.in = pcrextend_header; +- cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); +- memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); +- rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, +- "attempting extend a PCR value"); +- +- tpm_chip_put(chip); +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_pcr_extend); +- +-/** +- * tpm_do_selftest - have the TPM continue its selftest and wait until it +- * can receive further commands +- * @chip: TPM chip to use +- * +- * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing +- * a TPM error code. +- */ +-int tpm_do_selftest(struct tpm_chip *chip) +-{ +- int rc; +- unsigned int loops; +- unsigned int delay_msec = 1000; +- unsigned long duration; +- struct tpm_cmd_t cmd; +- +- duration = tpm_calc_ordinal_duration(chip, +- TPM_ORD_CONTINUE_SELFTEST); +- +- loops = jiffies_to_msecs(duration) / delay_msec; +- +- rc = tpm_continue_selftest(chip); +- /* This may fail if there was no TPM driver during a suspend/resume +- * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) +- */ +- if (rc) +- return rc; +- +- do { +- /* Attempt to read a PCR value */ +- cmd.header.in = pcrread_header; +- cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); +- rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); +- +- if (rc < TPM_HEADER_SIZE) +- return -EFAULT; +- +- rc = be32_to_cpu(cmd.header.out.return_code); +- if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { +- dev_info(chip->dev, +- "TPM is disabled/deactivated (0x%X)\n", rc); +- /* TPM is disabled and/or deactivated; driver can +- * proceed and TPM does handle commands for +- * suspend/resume correctly +- */ +- return 0; +- } +- if (rc != TPM_WARN_DOING_SELFTEST) +- return rc; +- msleep(delay_msec); +- } while (--loops > 0); +- +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_do_selftest); +- +-int tpm_send(u32 chip_num, void *cmd, size_t buflen) +-{ +- struct tpm_chip *chip; +- int rc; +- +- chip = tpm_chip_find_get(chip_num); +- if (chip == NULL) +- return -ENODEV; +- +- rc = transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd"); +- +- tpm_chip_put(chip); +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_send); +- +-ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- cap_t cap; +- u8 digest[TPM_DIGEST_SIZE]; +- ssize_t rc; +- int i, j, num_pcrs; +- char *str = buf; +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, +- "attempting to determine the number of PCRS"); +- if (rc) +- return 0; +- +- num_pcrs = be32_to_cpu(cap.num_pcrs); +- for (i = 0; i < num_pcrs; i++) { +- rc = __tpm_pcr_read(chip, i, digest); +- if (rc) +- break; +- str += sprintf(str, "PCR-%02d: ", i); +- for (j = 0; j < TPM_DIGEST_SIZE; j++) +- str += sprintf(str, "%02X ", digest[j]); +- str += sprintf(str, "\n"); +- } +- return str - buf; +-} +-EXPORT_SYMBOL_GPL(tpm_show_pcrs); +- +-#define READ_PUBEK_RESULT_SIZE 314 +-#define TPM_ORD_READPUBEK cpu_to_be32(124) +-static struct tpm_input_header tpm_readpubek_header = { +- .tag = TPM_TAG_RQU_COMMAND, +- .length = cpu_to_be32(30), +- .ordinal = TPM_ORD_READPUBEK +-}; +- +-ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- u8 *data; +- struct tpm_cmd_t tpm_cmd; +- ssize_t err; +- int i, rc; +- char *str = buf; +- +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- tpm_cmd.header.in = tpm_readpubek_header; +- err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, +- "attempting to read the PUBEK"); +- if (err) +- goto out; +- +- /* +- ignore header 10 bytes +- algorithm 32 bits (1 == RSA ) +- encscheme 16 bits +- sigscheme 16 bits +- parameters (RSA 12->bytes: keybit, #primes, expbit) +- keylenbytes 32 bits +- 256 byte modulus +- ignore checksum 20 bytes +- */ +- data = tpm_cmd.params.readpubek_out_buffer; +- str += +- sprintf(str, +- "Algorithm: %02X %02X %02X %02X\n" +- "Encscheme: %02X %02X\n" +- "Sigscheme: %02X %02X\n" +- "Parameters: %02X %02X %02X %02X " +- "%02X %02X %02X %02X " +- "%02X %02X %02X %02X\n" +- "Modulus length: %d\n" +- "Modulus:\n", +- data[0], data[1], data[2], data[3], +- data[4], data[5], +- data[6], data[7], +- data[12], data[13], data[14], data[15], +- data[16], data[17], data[18], data[19], +- data[20], data[21], data[22], data[23], +- be32_to_cpu(*((__be32 *) (data + 24)))); +- +- for (i = 0; i < 256; i++) { +- str += sprintf(str, "%02X ", data[i + 28]); +- if ((i + 1) % 16 == 0) +- str += sprintf(str, "\n"); +- } +-out: +- rc = str - buf; +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_show_pubek); +- +- +-ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- cap_t cap; +- ssize_t rc; +- char *str = buf; +- +- rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, +- "attempting to determine the manufacturer"); +- if (rc) +- return 0; +- str += sprintf(str, "Manufacturer: 0x%x\n", +- be32_to_cpu(cap.manufacturer_id)); +- +- rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap, +- "attempting to determine the 1.1 version"); +- if (rc) +- return 0; +- str += sprintf(str, +- "TCG version: %d.%d\nFirmware version: %d.%d\n", +- cap.tpm_version.Major, cap.tpm_version.Minor, +- cap.tpm_version.revMajor, cap.tpm_version.revMinor); +- return str - buf; +-} +-EXPORT_SYMBOL_GPL(tpm_show_caps); +- +-ssize_t tpm_show_caps_1_2(struct device * dev, +- struct device_attribute * attr, char *buf) +-{ +- cap_t cap; +- ssize_t rc; +- char *str = buf; +- +- rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, +- "attempting to determine the manufacturer"); +- if (rc) +- return 0; +- str += sprintf(str, "Manufacturer: 0x%x\n", +- be32_to_cpu(cap.manufacturer_id)); +- rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap, +- "attempting to determine the 1.2 version"); +- if (rc) +- return 0; +- str += sprintf(str, +- "TCG version: %d.%d\nFirmware version: %d.%d\n", +- cap.tpm_version_1_2.Major, cap.tpm_version_1_2.Minor, +- cap.tpm_version_1_2.revMajor, +- cap.tpm_version_1_2.revMinor); +- return str - buf; +-} +-EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); +- +-ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- if (chip->vendor.duration[TPM_LONG] == 0) +- return 0; +- +- return sprintf(buf, "%d %d %d [%s]\n", +- jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]), +- jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]), +- jiffies_to_usecs(chip->vendor.duration[TPM_LONG]), +- chip->vendor.duration_adjusted +- ? "adjusted" : "original"); +-} +-EXPORT_SYMBOL_GPL(tpm_show_durations); +- +-ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- return sprintf(buf, "%d %d %d %d [%s]\n", +- jiffies_to_usecs(chip->vendor.timeout_a), +- jiffies_to_usecs(chip->vendor.timeout_b), +- jiffies_to_usecs(chip->vendor.timeout_c), +- jiffies_to_usecs(chip->vendor.timeout_d), +- chip->vendor.timeout_adjusted +- ? "adjusted" : "original"); +-} +-EXPORT_SYMBOL_GPL(tpm_show_timeouts); +- +-ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct tpm_chip *chip = dev_get_drvdata(dev); +- if (chip == NULL) +- return 0; +- +- chip->vendor.cancel(chip); +- return count; +-} +-EXPORT_SYMBOL_GPL(tpm_store_cancel); +- +-int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, +- wait_queue_head_t *queue) +-{ +- unsigned long stop; +- long rc; +- u8 status; +- +- /* check current status */ +- status = chip->vendor.status(chip); +- if ((status & mask) == mask) +- return 0; +- +- stop = jiffies + timeout; +- +- if (chip->vendor.irq) { +-again: +- timeout = stop - jiffies; +- if ((long)timeout <= 0) +- return -ETIME; +- rc = wait_event_interruptible_timeout(*queue, +- ((chip->vendor.status(chip) +- & mask) == mask), +- timeout); +- if (rc > 0) +- return 0; +- if (rc == -ERESTARTSYS && freezing(current)) { +- clear_thread_flag(TIF_SIGPENDING); +- goto again; +- } +- } else { +- do { +- msleep(TPM_TIMEOUT); +- status = chip->vendor.status(chip); +- if ((status & mask) == mask) +- return 0; +- } while (time_before(jiffies, stop)); +- } +- return -ETIME; +-} +-EXPORT_SYMBOL_GPL(wait_for_tpm_stat); +-/* +- * Device file system interface to the TPM +- * +- * It's assured that the chip will be opened just once, +- * by the check of is_open variable, which is protected +- * by driver_lock. +- */ +-int tpm_open(struct inode *inode, struct file *file) +-{ +- int minor = iminor(inode); +- struct tpm_chip *chip = NULL, *pos; +- +- rcu_read_lock(); +- list_for_each_entry_rcu(pos, &tpm_chip_list, list) { +- if (pos->vendor.miscdev.minor == minor) { +- chip = pos; +- get_device(chip->dev); +- break; +- } +- } +- rcu_read_unlock(); +- +- if (!chip) +- return -ENODEV; +- +- if (test_and_set_bit(0, &chip->is_open)) { +- dev_dbg(chip->dev, "Another process owns this TPM\n"); +- put_device(chip->dev); +- return -EBUSY; +- } +- +- chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL); +- if (chip->data_buffer == NULL) { +- clear_bit(0, &chip->is_open); +- put_device(chip->dev); +- return -ENOMEM; +- } +- +- atomic_set(&chip->data_pending, 0); +- +- file->private_data = chip; +- return 0; +-} +-EXPORT_SYMBOL_GPL(tpm_open); +- +-/* +- * Called on file close +- */ +-int tpm_release(struct inode *inode, struct file *file) +-{ +- struct tpm_chip *chip = file->private_data; +- +- del_singleshot_timer_sync(&chip->user_read_timer); +- flush_work(&chip->work); +- file->private_data = NULL; +- atomic_set(&chip->data_pending, 0); +- kzfree(chip->data_buffer); +- clear_bit(0, &chip->is_open); +- put_device(chip->dev); +- return 0; +-} +-EXPORT_SYMBOL_GPL(tpm_release); +- +-ssize_t tpm_write(struct file *file, const char __user *buf, +- size_t size, loff_t *off) +-{ +- struct tpm_chip *chip = file->private_data; +- size_t in_size = size; +- ssize_t out_size; +- +- /* cannot perform a write until the read has cleared +- either via tpm_read or a user_read_timer timeout. +- This also prevents splitted buffered writes from blocking here. +- */ +- if (atomic_read(&chip->data_pending) != 0) +- return -EBUSY; +- +- if (in_size > TPM_BUFSIZE) +- return -E2BIG; +- +- mutex_lock(&chip->buffer_mutex); +- +- if (copy_from_user +- (chip->data_buffer, (void __user *) buf, in_size)) { +- mutex_unlock(&chip->buffer_mutex); +- return -EFAULT; +- } +- +- /* atomic tpm command send and result receive */ +- out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); +- if (out_size < 0) { +- mutex_unlock(&chip->buffer_mutex); +- return out_size; +- } +- +- atomic_set(&chip->data_pending, out_size); +- mutex_unlock(&chip->buffer_mutex); +- +- /* Set a timeout by which the reader must come claim the result */ +- mod_timer(&chip->user_read_timer, jiffies + (60 * HZ)); +- +- return in_size; +-} +-EXPORT_SYMBOL_GPL(tpm_write); +- +-ssize_t tpm_read(struct file *file, char __user *buf, +- size_t size, loff_t *off) +-{ +- struct tpm_chip *chip = file->private_data; +- ssize_t ret_size; +- int rc; +- +- del_singleshot_timer_sync(&chip->user_read_timer); +- flush_work(&chip->work); +- ret_size = atomic_read(&chip->data_pending); +- if (ret_size > 0) { /* relay data */ +- ssize_t orig_ret_size = ret_size; +- if (size < ret_size) +- ret_size = size; +- +- mutex_lock(&chip->buffer_mutex); +- rc = copy_to_user(buf, chip->data_buffer, ret_size); +- memset(chip->data_buffer, 0, orig_ret_size); +- if (rc) +- ret_size = -EFAULT; +- +- mutex_unlock(&chip->buffer_mutex); +- } +- +- atomic_set(&chip->data_pending, 0); +- +- return ret_size; +-} +-EXPORT_SYMBOL_GPL(tpm_read); +- +-void tpm_remove_hardware(struct device *dev) +-{ +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- if (chip == NULL) { +- dev_err(dev, "No device data found\n"); +- return; +- } +- +- spin_lock(&driver_lock); +- list_del_rcu(&chip->list); +- spin_unlock(&driver_lock); +- synchronize_rcu(); +- +- misc_deregister(&chip->vendor.miscdev); +- sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); +- tpm_remove_ppi(&dev->kobj); +- tpm_bios_log_teardown(chip->bios_dir); +- +- /* write it this way to be explicit (chip->dev == dev) */ +- put_device(chip->dev); +-} +-EXPORT_SYMBOL_GPL(tpm_remove_hardware); +- +-#define TPM_ORD_SAVESTATE cpu_to_be32(152) +-#define SAVESTATE_RESULT_SIZE 10 +- +-static struct tpm_input_header savestate_header = { +- .tag = TPM_TAG_RQU_COMMAND, +- .length = cpu_to_be32(10), +- .ordinal = TPM_ORD_SAVESTATE +-}; +- +-/* +- * We are about to suspend. Save the TPM state +- * so that it can be restored. +- */ +-int tpm_pm_suspend(struct device *dev) +-{ +- struct tpm_chip *chip = dev_get_drvdata(dev); +- struct tpm_cmd_t cmd; +- int rc, try; +- +- u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; +- +- if (chip == NULL) +- return -ENODEV; +- +- /* for buggy tpm, flush pcrs with extend to selected dummy */ +- if (tpm_suspend_pcr) { +- cmd.header.in = pcrextend_header; +- cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); +- memcpy(cmd.params.pcrextend_in.hash, dummy_hash, +- TPM_DIGEST_SIZE); +- rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, +- "extending dummy pcr before suspend"); +- } +- +- /* now do the actual savestate */ +- for (try = 0; try < TPM_RETRY; try++) { +- cmd.header.in = savestate_header; +- rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL); +- +- /* +- * If the TPM indicates that it is too busy to respond to +- * this command then retry before giving up. It can take +- * several seconds for this TPM to be ready. +- * +- * This can happen if the TPM has already been sent the +- * SaveState command before the driver has loaded. TCG 1.2 +- * specification states that any communication after SaveState +- * may cause the TPM to invalidate previously saved state. +- */ +- if (rc != TPM_WARN_RETRY) +- break; +- msleep(TPM_TIMEOUT_RETRY); +- } +- +- if (rc) +- dev_err(chip->dev, +- "Error (%d) sending savestate before suspend\n", rc); +- else if (try > 0) +- dev_warn(chip->dev, "TPM savestate took %dms\n", +- try * TPM_TIMEOUT_RETRY); +- +- return rc; +-} +-EXPORT_SYMBOL_GPL(tpm_pm_suspend); +- +-/* +- * Resume from a power safe. The BIOS already restored +- * the TPM state. +- */ +-int tpm_pm_resume(struct device *dev) +-{ +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- if (chip == NULL) +- return -ENODEV; +- +- return 0; +-} +-EXPORT_SYMBOL_GPL(tpm_pm_resume); +- +-#define TPM_GETRANDOM_RESULT_SIZE 18 +-static struct tpm_input_header tpm_getrandom_header = { +- .tag = TPM_TAG_RQU_COMMAND, +- .length = cpu_to_be32(14), +- .ordinal = TPM_ORD_GET_RANDOM +-}; +- +-/** +- * tpm_get_random() - Get random bytes from the tpm's RNG +- * @chip_num: A specific chip number for the request or TPM_ANY_NUM +- * @out: destination buffer for the random bytes +- * @max: the max number of bytes to write to @out +- * +- * Returns < 0 on error and the number of bytes read on success +- */ +-int tpm_get_random(u32 chip_num, u8 *out, size_t max) +-{ +- struct tpm_chip *chip; +- struct tpm_cmd_t tpm_cmd; +- u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA); +- int err, total = 0, retries = 5; +- u8 *dest = out; +- +- chip = tpm_chip_find_get(chip_num); +- if (chip == NULL) +- return -ENODEV; +- +- if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) +- return -EINVAL; +- +- do { +- tpm_cmd.header.in = tpm_getrandom_header; +- tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); +- +- err = transmit_cmd(chip, &tpm_cmd, +- TPM_GETRANDOM_RESULT_SIZE + num_bytes, +- "attempting get random"); +- if (err) +- break; +- +- recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); +- memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd); +- +- dest += recd; +- total += recd; +- num_bytes -= recd; +- } while (retries-- && total < max); +- +- return total ? total : -EIO; +-} +-EXPORT_SYMBOL_GPL(tpm_get_random); +- +-/* In case vendor provided release function, call it too.*/ +- +-void tpm_dev_vendor_release(struct tpm_chip *chip) +-{ +- if (!chip) +- return; +- +- if (chip->vendor.release) +- chip->vendor.release(chip->dev); +- +- clear_bit(chip->dev_num, dev_mask); +- kfree(chip->vendor.miscdev.name); +-} +-EXPORT_SYMBOL_GPL(tpm_dev_vendor_release); +- +- +-/* +- * Once all references to platform device are down to 0, +- * release all allocated structures. +- */ +-static void tpm_dev_release(struct device *dev) +-{ +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- if (!chip) +- return; +- +- tpm_dev_vendor_release(chip); +- +- chip->release(dev); +- kfree(chip); +-} +-EXPORT_SYMBOL_GPL(tpm_dev_release); +- +-/* +- * Called from tpm_.c probe function only for devices +- * the driver has determined it should claim. Prior to calling +- * this function the specific probe function has called pci_enable_device +- * upon errant exit from this function specific probe function should call +- * pci_disable_device +- */ +-struct tpm_chip *tpm_register_hardware(struct device *dev, +- const struct tpm_vendor_specific *entry) +-{ +-#define DEVNAME_SIZE 7 +- +- char *devname; +- struct tpm_chip *chip; +- +- /* Driver specific per-device data */ +- chip = kzalloc(sizeof(*chip), GFP_KERNEL); +- devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); +- +- if (chip == NULL || devname == NULL) +- goto out_free; +- +- mutex_init(&chip->buffer_mutex); +- mutex_init(&chip->tpm_mutex); +- INIT_LIST_HEAD(&chip->list); +- +- INIT_WORK(&chip->work, timeout_work); +- +- setup_timer(&chip->user_read_timer, user_reader_timeout, +- (unsigned long)chip); +- +- memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); +- +- chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); +- +- if (chip->dev_num >= TPM_NUM_DEVICES) { +- dev_err(dev, "No available tpm device numbers\n"); +- goto out_free; +- } else if (chip->dev_num == 0) +- chip->vendor.miscdev.minor = TPM_MINOR; +- else +- chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; +- +- set_bit(chip->dev_num, dev_mask); +- +- scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); +- chip->vendor.miscdev.name = devname; +- +- chip->vendor.miscdev.parent = dev; +- chip->dev = get_device(dev); +- chip->release = dev->release; +- dev->release = tpm_dev_release; +- dev_set_drvdata(dev, chip); +- +- if (misc_register(&chip->vendor.miscdev)) { +- dev_err(chip->dev, +- "unable to misc_register %s, minor %d\n", +- chip->vendor.miscdev.name, +- chip->vendor.miscdev.minor); +- goto put_device; +- } +- +- if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { +- misc_deregister(&chip->vendor.miscdev); +- goto put_device; +- } +- +- if (tpm_add_ppi(&dev->kobj)) { +- misc_deregister(&chip->vendor.miscdev); +- goto put_device; +- } +- +- chip->bios_dir = tpm_bios_log_setup(devname); +- +- /* Make chip available */ +- spin_lock(&driver_lock); +- list_add_rcu(&chip->list, &tpm_chip_list); +- spin_unlock(&driver_lock); +- +- return chip; +- +-put_device: +- put_device(chip->dev); +-out_free: +- kfree(chip); +- kfree(devname); +- return NULL; +-} +-EXPORT_SYMBOL_GPL(tpm_register_hardware); +- +-MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); +-MODULE_DESCRIPTION("TPM Driver"); +-MODULE_VERSION("2.0"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h +index 9c12a52..f328478 100644 +--- a/drivers/char/tpm/tpm.h ++++ b/drivers/char/tpm/tpm.h +@@ -50,6 +50,7 @@ enum tpm_addr { + #define TPM_WARN_DOING_SELFTEST 0x802 + #define TPM_ERR_DEACTIVATED 0x6 + #define TPM_ERR_DISABLED 0x7 ++#define TPM_ERR_INVALID_POSTINIT 38 + + #define TPM_HEADER_SIZE 10 + extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, +@@ -58,8 +59,6 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, + char *); + extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, + char *); +-extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr, +- char *); + extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, + const char *, size_t); + extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr, +@@ -80,7 +79,7 @@ struct tpm_chip; + struct tpm_vendor_specific { + const u8 req_complete_mask; + const u8 req_complete_val; +- const u8 req_canceled; ++ bool (*req_canceled)(struct tpm_chip *chip, u8 status); + void __iomem *iobase; /* ioremapped address */ + unsigned long base; /* TPM base address */ + +@@ -103,18 +102,25 @@ struct tpm_vendor_specific { + bool timeout_adjusted; + unsigned long duration[3]; /* jiffies */ + bool duration_adjusted; +- void *data; ++ void *priv; + + wait_queue_head_t read_queue; + wait_queue_head_t int_queue; ++ ++ u16 manufacturer_id; + }; + ++#define TPM_VPRIV(c) (c)->vendor.priv ++ + #define TPM_VID_INTEL 0x8086 ++#define TPM_VID_WINBOND 0x1050 ++#define TPM_VID_STM 0x104A + + struct tpm_chip { + struct device *dev; /* Device stuff */ + + int dev_num; /* /dev/tpm# */ ++ char devname[7]; + unsigned long is_open; /* only one allowed */ + int time_expired; + +@@ -157,13 +163,13 @@ struct tpm_input_header { + __be16 tag; + __be32 length; + __be32 ordinal; +-}__attribute__((packed)); ++} __packed; + + struct tpm_output_header { + __be16 tag; + __be32 length; + __be32 return_code; +-}__attribute__((packed)); ++} __packed; + + struct stclear_flags_t { + __be16 tag; +@@ -172,14 +178,14 @@ struct stclear_flags_t { + u8 physicalPresence; + u8 physicalPresenceLock; + u8 bGlobalLock; +-}__attribute__((packed)); ++} __packed; + + struct tpm_version_t { + u8 Major; + u8 Minor; + u8 revMajor; + u8 revMinor; +-}__attribute__((packed)); ++} __packed; + + struct tpm_version_1_2_t { + __be16 tag; +@@ -187,20 +193,20 @@ struct tpm_version_1_2_t { + u8 Minor; + u8 revMajor; + u8 revMinor; +-}__attribute__((packed)); ++} __packed; + + struct timeout_t { + __be32 a; + __be32 b; + __be32 c; + __be32 d; +-}__attribute__((packed)); ++} __packed; + + struct duration_t { + __be32 tpm_short; + __be32 tpm_medium; + __be32 tpm_long; +-}__attribute__((packed)); ++} __packed; + + struct permanent_flags_t { + __be16 tag; +@@ -224,7 +230,7 @@ struct permanent_flags_t { + u8 tpmEstablished; + u8 maintenanceDone; + u8 disableFullDALogicInfo; +-}__attribute__((packed)); ++} __packed; + + typedef union { + struct permanent_flags_t perm_flags; +@@ -242,12 +248,12 @@ struct tpm_getcap_params_in { + __be32 cap; + __be32 subcap_size; + __be32 subcap; +-}__attribute__((packed)); ++} __packed; + + struct tpm_getcap_params_out { + __be32 cap_size; + cap_t cap; +-}__attribute__((packed)); ++} __packed; + + struct tpm_readpubek_params_out { + u8 algorithm[4]; +@@ -258,26 +264,25 @@ struct tpm_readpubek_params_out { + __be32 keysize; + u8 modulus[256]; + u8 checksum[20]; +-}__attribute__((packed)); ++} __packed; + + typedef union { + struct tpm_input_header in; + struct tpm_output_header out; + } tpm_cmd_header; + +-#define TPM_DIGEST_SIZE 20 + struct tpm_pcrread_out { + u8 pcr_result[TPM_DIGEST_SIZE]; +-}__attribute__((packed)); ++} __packed; + + struct tpm_pcrread_in { + __be32 pcr_idx; +-}__attribute__((packed)); ++} __packed; + + struct tpm_pcrextend_in { + __be32 pcr_idx; + u8 hash[TPM_DIGEST_SIZE]; +-}__attribute__((packed)); ++} __packed; + + /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 + * bytes, but 128 is still a relatively large number of random bytes and +@@ -288,11 +293,15 @@ struct tpm_pcrextend_in { + struct tpm_getrandom_out { + __be32 rng_data_len; + u8 rng_data[TPM_MAX_RNG_DATA]; +-}__attribute__((packed)); ++} __packed; + + struct tpm_getrandom_in { + __be32 num_bytes; +-}__attribute__((packed)); ++} __packed; ++ ++struct tpm_startup_in { ++ __be16 startup_type; ++} __packed; + + typedef union { + struct tpm_getcap_params_out getcap_out; +@@ -304,12 +313,13 @@ typedef union { + struct tpm_pcrextend_in pcrextend_in; + struct tpm_getrandom_in getrandom_in; + struct tpm_getrandom_out getrandom_out; ++ struct tpm_startup_in startup_in; + } tpm_cmd_params; + + struct tpm_cmd_t { + tpm_cmd_header header; + tpm_cmd_params params; +-}__attribute__((packed)); ++} __packed; + + ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); + +@@ -321,6 +331,7 @@ extern struct tpm_chip* tpm_register_hardware(struct device *, + const struct tpm_vendor_specific *); + extern int tpm_open(struct inode *, struct file *); + extern int tpm_release(struct inode *, struct file *); ++extern void tpm_dev_release(struct device *dev); + extern void tpm_dev_vendor_release(struct tpm_chip *); + extern ssize_t tpm_write(struct file *, const char __user *, size_t, + loff_t *); +@@ -329,7 +340,7 @@ extern void tpm_remove_hardware(struct device *); + extern int tpm_pm_suspend(struct device *); + extern int tpm_pm_resume(struct device *); + extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, +- wait_queue_head_t *); ++ wait_queue_head_t *, bool); + + #ifdef CONFIG_ACPI + extern int tpm_add_ppi(struct kobject *); +diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c +index 56051d0..64420b3 100644 +--- a/drivers/char/tpm/tpm_acpi.c ++++ b/drivers/char/tpm/tpm_acpi.c +@@ -33,13 +33,13 @@ struct acpi_tcpa { + u16 platform_class; + union { + struct client_hdr { +- u32 log_max_len __attribute__ ((packed)); +- u64 log_start_addr __attribute__ ((packed)); ++ u32 log_max_len __packed; ++ u64 log_start_addr __packed; + } client; + struct server_hdr { + u16 reserved; +- u64 log_max_len __attribute__ ((packed)); +- u64 log_start_addr __attribute__ ((packed)); ++ u64 log_max_len __packed; ++ u64 log_start_addr __packed; + } server; + }; + }; +diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c +index 678d570..c9a528d 100644 +--- a/drivers/char/tpm/tpm_atmel.c ++++ b/drivers/char/tpm/tpm_atmel.c +@@ -116,6 +116,11 @@ static u8 tpm_atml_status(struct tpm_chip *chip) + return ioread8(chip->vendor.iobase + 1); + } + ++static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status) ++{ ++ return (status == ATML_STATUS_READY); ++} ++ + static const struct file_operations atmel_ops = { + .owner = THIS_MODULE, + .llseek = no_llseek, +@@ -147,7 +152,7 @@ static const struct tpm_vendor_specific tpm_atmel = { + .status = tpm_atml_status, + .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, + .req_complete_val = ATML_STATUS_DATA_AVAIL, +- .req_canceled = ATML_STATUS_READY, ++ .req_canceled = tpm_atml_req_canceled, + .attr_group = &atmel_attr_grp, + .miscdev = { .fops = &atmel_ops, }, + }; +@@ -197,7 +202,7 @@ static int __init init_atmel(void) + + have_region = + (atmel_request_region +- (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; ++ (base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; + + pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0); + if (IS_ERR(pdev)) { +diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c +index 84ddc55..59f7cb2 100644 +--- a/drivers/char/tpm/tpm_eventlog.c ++++ b/drivers/char/tpm/tpm_eventlog.c +@@ -406,7 +406,6 @@ out_tpm: + out: + return NULL; + } +-EXPORT_SYMBOL_GPL(tpm_bios_log_setup); + + void tpm_bios_log_teardown(struct dentry **lst) + { +@@ -415,5 +414,3 @@ void tpm_bios_log_teardown(struct dentry **lst) + for (i = 0; i < 3; i++) + securityfs_remove(lst[i]); + } +-EXPORT_SYMBOL_GPL(tpm_bios_log_teardown); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c +new file mode 100644 +index 0000000..c3cd7fe +--- /dev/null ++++ b/drivers/char/tpm/tpm_i2c_atmel.c +@@ -0,0 +1,284 @@ ++/* ++ * ATMEL I2C TPM AT97SC3204T ++ * ++ * Copyright (C) 2012 V Lab Technologies ++ * Teddy Reed ++ * Copyright (C) 2013, Obsidian Research Corp. ++ * Jason Gunthorpe ++ * Device driver for ATMEL I2C TPMs. ++ * ++ * Teddy Reed determined the basic I2C command flow, unlike other I2C TPM ++ * devices the raw TCG formatted TPM command data is written via I2C and then ++ * raw TCG formatted TPM command data is returned via I2C. ++ * ++ * TGC status/locality/etc functions seen in the LPC implementation do not ++ * seem to be present. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see http://www.gnu.org/licenses/>. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include "tpm.h" ++ ++#define I2C_DRIVER_NAME "tpm_i2c_atmel" ++ ++#define TPM_I2C_SHORT_TIMEOUT 750 /* ms */ ++#define TPM_I2C_LONG_TIMEOUT 2000 /* 2 sec */ ++ ++#define ATMEL_STS_OK 1 ++ ++struct priv_data { ++ size_t len; ++ /* This is the amount we read on the first try. 25 was chosen to fit a ++ * fair number of read responses in the buffer so a 2nd retry can be ++ * avoided in small message cases. */ ++ u8 buffer[sizeof(struct tpm_output_header) + 25]; ++}; ++ ++static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) ++{ ++ struct priv_data *priv = chip->vendor.priv; ++ struct i2c_client *client = to_i2c_client(chip->dev); ++ s32 status; ++ ++ priv->len = 0; ++ ++ if (len <= 2) ++ return -EIO; ++ ++ status = i2c_master_send(client, buf, len); ++ ++ dev_dbg(chip->dev, ++ "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, ++ (int)min_t(size_t, 64, len), buf, len, status); ++ return status; ++} ++ ++static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) ++{ ++ struct priv_data *priv = chip->vendor.priv; ++ struct i2c_client *client = to_i2c_client(chip->dev); ++ struct tpm_output_header *hdr = ++ (struct tpm_output_header *)priv->buffer; ++ u32 expected_len; ++ int rc; ++ ++ if (priv->len == 0) ++ return -EIO; ++ ++ /* Get the message size from the message header, if we didn't get the ++ * whole message in read_status then we need to re-read the ++ * message. */ ++ expected_len = be32_to_cpu(hdr->length); ++ if (expected_len > count) ++ return -ENOMEM; ++ ++ if (priv->len >= expected_len) { ++ dev_dbg(chip->dev, ++ "%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__, ++ (int)min_t(size_t, 64, expected_len), buf, count, ++ expected_len); ++ memcpy(buf, priv->buffer, expected_len); ++ return expected_len; ++ } ++ ++ rc = i2c_master_recv(client, buf, expected_len); ++ dev_dbg(chip->dev, ++ "%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__, ++ (int)min_t(size_t, 64, expected_len), buf, count, ++ expected_len); ++ return rc; ++} ++ ++static void i2c_atmel_cancel(struct tpm_chip *chip) ++{ ++ dev_err(chip->dev, "TPM operation cancellation was requested, but is not supported"); ++} ++ ++static u8 i2c_atmel_read_status(struct tpm_chip *chip) ++{ ++ struct priv_data *priv = chip->vendor.priv; ++ struct i2c_client *client = to_i2c_client(chip->dev); ++ int rc; ++ ++ /* The TPM fails the I2C read until it is ready, so we do the entire ++ * transfer here and buffer it locally. This way the common code can ++ * properly handle the timeouts. */ ++ priv->len = 0; ++ memset(priv->buffer, 0, sizeof(priv->buffer)); ++ ++ ++ /* Once the TPM has completed the command the command remains readable ++ * until another command is issued. */ ++ rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer)); ++ dev_dbg(chip->dev, ++ "%s: sts=%d", __func__, rc); ++ if (rc <= 0) ++ return 0; ++ ++ priv->len = rc; ++ ++ return ATMEL_STS_OK; ++} ++ ++static const struct file_operations i2c_atmel_ops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .open = tpm_open, ++ .read = tpm_read, ++ .write = tpm_write, ++ .release = tpm_release, ++}; ++ ++static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); ++static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); ++static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); ++static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); ++static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); ++static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL); ++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); ++static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); ++static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL); ++static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); ++ ++static struct attribute *i2c_atmel_attrs[] = { ++ &dev_attr_pubek.attr, ++ &dev_attr_pcrs.attr, ++ &dev_attr_enabled.attr, ++ &dev_attr_active.attr, ++ &dev_attr_owned.attr, ++ &dev_attr_temp_deactivated.attr, ++ &dev_attr_caps.attr, ++ &dev_attr_cancel.attr, ++ &dev_attr_durations.attr, ++ &dev_attr_timeouts.attr, ++ NULL, ++}; ++ ++static struct attribute_group i2c_atmel_attr_grp = { ++ .attrs = i2c_atmel_attrs ++}; ++ ++static bool i2c_atmel_req_canceled(struct tpm_chip *chip, u8 status) ++{ ++ return 0; ++} ++ ++static const struct tpm_vendor_specific i2c_atmel = { ++ .status = i2c_atmel_read_status, ++ .recv = i2c_atmel_recv, ++ .send = i2c_atmel_send, ++ .cancel = i2c_atmel_cancel, ++ .req_complete_mask = ATMEL_STS_OK, ++ .req_complete_val = ATMEL_STS_OK, ++ .req_canceled = i2c_atmel_req_canceled, ++ .attr_group = &i2c_atmel_attr_grp, ++ .miscdev.fops = &i2c_atmel_ops, ++}; ++ ++static int i2c_atmel_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int rc; ++ struct tpm_chip *chip; ++ struct device *dev = &client->dev; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) ++ return -ENODEV; ++ ++ chip = tpm_register_hardware(dev, &i2c_atmel); ++ if (!chip) { ++ dev_err(dev, "%s() error in tpm_register_hardware\n", __func__); ++ return -ENODEV; ++ } ++ ++ chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), ++ GFP_KERNEL); ++ ++ /* Default timeouts */ ++ chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); ++ chip->vendor.timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT); ++ chip->vendor.timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); ++ chip->vendor.timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); ++ chip->vendor.irq = 0; ++ ++ /* There is no known way to probe for this device, and all version ++ * information seems to be read via TPM commands. Thus we rely on the ++ * TPM startup process in the common code to detect the device. */ ++ if (tpm_get_timeouts(chip)) { ++ rc = -ENODEV; ++ goto out_err; ++ } ++ ++ if (tpm_do_selftest(chip)) { ++ rc = -ENODEV; ++ goto out_err; ++ } ++ ++ return 0; ++ ++out_err: ++ tpm_dev_vendor_release(chip); ++ tpm_remove_hardware(chip->dev); ++ return rc; ++} ++ ++static int i2c_atmel_remove(struct i2c_client *client) ++{ ++ struct device *dev = &(client->dev); ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ ++ if (chip) ++ tpm_dev_vendor_release(chip); ++ tpm_remove_hardware(dev); ++ kfree(chip); ++ return 0; ++} ++ ++static const struct i2c_device_id i2c_atmel_id[] = { ++ {I2C_DRIVER_NAME, 0}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, i2c_atmel_id); ++ ++#ifdef CONFIG_OF ++static const struct of_device_id i2c_atmel_of_match[] = { ++ {.compatible = "atmel,at97sc3204t"}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, i2c_atmel_of_match); ++#endif ++ ++static SIMPLE_DEV_PM_OPS(i2c_atmel_pm_ops, tpm_pm_suspend, tpm_pm_resume); ++ ++static struct i2c_driver i2c_atmel_driver = { ++ .id_table = i2c_atmel_id, ++ .probe = i2c_atmel_probe, ++ .remove = i2c_atmel_remove, ++ .driver = { ++ .name = I2C_DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .pm = &i2c_atmel_pm_ops, ++ .of_match_table = of_match_ptr(i2c_atmel_of_match), ++ }, ++}; ++ ++module_i2c_driver(i2c_atmel_driver); ++ ++MODULE_AUTHOR("Jason Gunthorpe "); ++MODULE_DESCRIPTION("Atmel TPM I2C Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c +index fb447bd..fefd2aa 100644 +--- a/drivers/char/tpm/tpm_i2c_infineon.c ++++ b/drivers/char/tpm/tpm_i2c_infineon.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2012 Infineon Technologies ++ * Copyright (C) 2012,2013 Infineon Technologies + * + * Authors: + * Peter Huewe +@@ -24,7 +24,6 @@ + #include + #include + #include +-#include + #include + #include "tpm.h" + +@@ -56,17 +55,24 @@ + #define TPM_TIMEOUT_US_HI (TPM_TIMEOUT_US_LOW + 2000) + + /* expected value for DIDVID register */ +-#define TPM_TIS_I2C_DID_VID 0x000b15d1L ++#define TPM_TIS_I2C_DID_VID_9635 0xd1150b00L ++#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L ++ ++enum i2c_chip_type { ++ SLB9635, ++ SLB9645, ++ UNKNOWN, ++}; + + /* Structure to store I2C TPM specific stuff */ + struct tpm_inf_dev { + struct i2c_client *client; + u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ + struct tpm_chip *chip; ++ enum i2c_chip_type chip_type; + }; + + static struct tpm_inf_dev tpm_dev; +-static struct i2c_driver tpm_tis_i2c_driver; + + /* + * iic_tpm_read() - read from TPM register +@@ -90,10 +96,20 @@ static struct i2c_driver tpm_tis_i2c_driver; + static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) + { + +- struct i2c_msg msg1 = { tpm_dev.client->addr, 0, 1, &addr }; +- struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer }; ++ struct i2c_msg msg1 = { ++ .addr = tpm_dev.client->addr, ++ .len = 1, ++ .buf = &addr ++ }; ++ struct i2c_msg msg2 = { ++ .addr = tpm_dev.client->addr, ++ .flags = I2C_M_RD, ++ .len = len, ++ .buf = buffer ++ }; ++ struct i2c_msg msgs[] = {msg1, msg2}; + +- int rc; ++ int rc = 0; + int count; + + /* Lock the adapter for the duration of the whole sequence. */ +@@ -101,30 +117,53 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) + return -EOPNOTSUPP; + i2c_lock_adapter(tpm_dev.client->adapter); + +- for (count = 0; count < MAX_COUNT; count++) { +- rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); +- if (rc > 0) +- break; /* break here to skip sleep */ +- +- usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); +- } +- +- if (rc <= 0) +- goto out; +- +- /* After the TPM has successfully received the register address it needs +- * some time, thus we're sleeping here again, before retrieving the data +- */ +- for (count = 0; count < MAX_COUNT; count++) { +- usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); +- rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); +- if (rc > 0) +- break; ++ if (tpm_dev.chip_type == SLB9645) { ++ /* use a combined read for newer chips ++ * unfortunately the smbus functions are not suitable due to ++ * the 32 byte limit of the smbus. ++ * retries should usually not be needed, but are kept just to ++ * be on the safe side. ++ */ ++ for (count = 0; count < MAX_COUNT; count++) { ++ rc = __i2c_transfer(tpm_dev.client->adapter, msgs, 2); ++ if (rc > 0) ++ break; /* break here to skip sleep */ ++ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); ++ } ++ } else { ++ /* slb9635 protocol should work in all cases */ ++ for (count = 0; count < MAX_COUNT; count++) { ++ rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); ++ if (rc > 0) ++ break; /* break here to skip sleep */ ++ ++ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); ++ } + ++ if (rc <= 0) ++ goto out; ++ ++ /* After the TPM has successfully received the register address ++ * it needs some time, thus we're sleeping here again, before ++ * retrieving the data ++ */ ++ for (count = 0; count < MAX_COUNT; count++) { ++ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); ++ rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); ++ if (rc > 0) ++ break; ++ } + } + + out: + i2c_unlock_adapter(tpm_dev.client->adapter); ++ /* take care of 'guard time' */ ++ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); ++ ++ /* __i2c_transfer returns the number of successfully transferred ++ * messages. ++ * So rc should be greater than 0 here otherwise we have an error. ++ */ + if (rc <= 0) + return -EIO; + +@@ -138,7 +177,11 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, + int rc = -EIO; + int count; + +- struct i2c_msg msg1 = { tpm_dev.client->addr, 0, len + 1, tpm_dev.buf }; ++ struct i2c_msg msg1 = { ++ .addr = tpm_dev.client->addr, ++ .len = len + 1, ++ .buf = tpm_dev.buf ++ }; + + if (len > TPM_BUFSIZE) + return -EINVAL; +@@ -154,16 +197,24 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, + /* + * NOTE: We have to use these special mechanisms here and unfortunately + * cannot rely on the standard behavior of i2c_transfer. ++ * Even for newer chips the smbus functions are not ++ * suitable due to the 32 byte limit of the smbus. + */ + for (count = 0; count < max_count; count++) { + rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); + if (rc > 0) + break; +- + usleep_range(sleep_low, sleep_hi); + } + + i2c_unlock_adapter(tpm_dev.client->adapter); ++ /* take care of 'guard time' */ ++ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); ++ ++ /* __i2c_transfer returns the number of successfully transferred ++ * messages. ++ * So rc should be greater than 0 here otherwise we have an error. ++ */ + if (rc <= 0) + return -EIO; + +@@ -283,11 +334,18 @@ static int request_locality(struct tpm_chip *chip, int loc) + static u8 tpm_tis_i2c_status(struct tpm_chip *chip) + { + /* NOTE: since I2C read may fail, return 0 in this case --> time-out */ +- u8 buf; +- if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) +- return 0; +- else +- return buf; ++ u8 buf = 0xFF; ++ u8 i = 0; ++ ++ do { ++ if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) ++ return 0; ++ ++ i++; ++ /* if locallity is set STS should not be 0xFF */ ++ } while ((buf == 0xFF) && i < 10); ++ ++ return buf; + } + + static void tpm_tis_i2c_ready(struct tpm_chip *chip) +@@ -328,7 +386,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, + + /* check current status */ + *status = tpm_tis_i2c_status(chip); +- if ((*status & mask) == mask) ++ if ((*status != 0xFF) && (*status & mask) == mask) + return 0; + + stop = jiffies + timeout; +@@ -372,7 +430,6 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) + /* avoid endless loop in case of broken HW */ + if (retries > MAX_COUNT_LONG) + return -EIO; +- + } + return size; + } +@@ -480,7 +537,6 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) + rc = -EIO; + goto out_err; + } +- + } + + /* write last byte */ +@@ -505,6 +561,11 @@ out_err: + return rc; + } + ++static bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status) ++{ ++ return (status == TPM_STS_COMMAND_READY); ++} ++ + static const struct file_operations tis_ops = { + .owner = THIS_MODULE, + .llseek = no_llseek, +@@ -520,7 +581,7 @@ static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); + static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); + static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); + static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL); +-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); ++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); + static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); + static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL); + static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); +@@ -550,7 +611,7 @@ static struct tpm_vendor_specific tpm_tis_i2c = { + .cancel = tpm_tis_i2c_ready, + .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, +- .req_canceled = TPM_STS_COMMAND_READY, ++ .req_canceled = tpm_tis_i2c_req_canceled, + .attr_group = &tis_attr_grp, + .miscdev.fops = &tis_ops, + }; +@@ -563,6 +624,7 @@ static int tpm_tis_i2c_init(struct device *dev) + + chip = tpm_register_hardware(dev, &tpm_tis_i2c); + if (!chip) { ++ dev_err(dev, "could not register hardware\n"); + rc = -ENODEV; + goto out_err; + } +@@ -577,20 +639,24 @@ static int tpm_tis_i2c_init(struct device *dev) + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + + if (request_locality(chip, 0) != 0) { ++ dev_err(dev, "could not request locality\n"); + rc = -ENODEV; + goto out_vendor; + } + + /* read four bytes from DID_VID register */ + if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) { ++ dev_err(dev, "could not read vendor id\n"); + rc = -EIO; + goto out_release; + } + +- /* create DID_VID register value, after swapping to little-endian */ +- vendor = be32_to_cpu((__be32) vendor); +- +- if (vendor != TPM_TIS_I2C_DID_VID) { ++ if (vendor == TPM_TIS_I2C_DID_VID_9645) { ++ tpm_dev.chip_type = SLB9645; ++ } else if (vendor == TPM_TIS_I2C_DID_VID_9635) { ++ tpm_dev.chip_type = SLB9635; ++ } else { ++ dev_err(dev, "vendor id did not match! ID was %08x\n", vendor); + rc = -ENODEV; + goto out_release; + } +@@ -619,37 +685,65 @@ out_vendor: + chip->dev->release = NULL; + chip->release = NULL; + tpm_dev.client = NULL; +- dev_set_drvdata(chip->dev, chip); + out_err: + return rc; + } + + static const struct i2c_device_id tpm_tis_i2c_table[] = { + {"tpm_i2c_infineon", 0}, ++ {"slb9635tt", 0}, ++ {"slb9645tt", 1}, + {}, + }; + + MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table); ++ ++#ifdef CONFIG_OF ++static const struct of_device_id tpm_tis_i2c_of_match[] = { ++ { ++ .name = "tpm_i2c_infineon", ++ .type = "tpm", ++ .compatible = "infineon,tpm_i2c_infineon", ++ .data = (void *)0 ++ }, ++ { ++ .name = "slb9635tt", ++ .type = "tpm", ++ .compatible = "infineon,slb9635tt", ++ .data = (void *)0 ++ }, ++ { ++ .name = "slb9645tt", ++ .type = "tpm", ++ .compatible = "infineon,slb9645tt", ++ .data = (void *)1 ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, tpm_tis_i2c_of_match); ++#endif ++ + static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); + + static int tpm_tis_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { + int rc; +- if (tpm_dev.client != NULL) ++ struct device *dev = &(client->dev); ++ ++ if (tpm_dev.client != NULL) { ++ dev_err(dev, "This driver only supports one client at a time\n"); + return -EBUSY; /* We only support one client */ ++ } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { +- dev_err(&client->dev, +- "no algorithms associated to the i2c bus\n"); ++ dev_err(dev, "no algorithms associated to the i2c bus\n"); + return -ENODEV; + } + +- client->driver = &tpm_tis_i2c_driver; + tpm_dev.client = client; + rc = tpm_tis_i2c_init(&client->dev); + if (rc != 0) { +- client->driver = NULL; + tpm_dev.client = NULL; + rc = -ENODEV; + } +@@ -671,13 +765,11 @@ static int tpm_tis_i2c_remove(struct i2c_client *client) + chip->dev->release = NULL; + chip->release = NULL; + tpm_dev.client = NULL; +- dev_set_drvdata(chip->dev, chip); + + return 0; + } + + static struct i2c_driver tpm_tis_i2c_driver = { +- + .id_table = tpm_tis_i2c_table, + .probe = tpm_tis_i2c_probe, + .remove = tpm_tis_i2c_remove, +@@ -685,11 +777,12 @@ static struct i2c_driver tpm_tis_i2c_driver = { + .name = "tpm_i2c_infineon", + .owner = THIS_MODULE, + .pm = &tpm_tis_i2c_ops, ++ .of_match_table = of_match_ptr(tpm_tis_i2c_of_match), + }, + }; + + module_i2c_driver(tpm_tis_i2c_driver); + MODULE_AUTHOR("Peter Huewe "); + MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver"); +-MODULE_VERSION("2.1.5"); ++MODULE_VERSION("2.2.0"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c +index 9978609..2783a42 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.c ++++ b/drivers/char/tpm/tpm_ibmvtpm.c +@@ -64,7 +64,7 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev) + { + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip) +- return (struct ibmvtpm_dev *)chip->vendor.data; ++ return (struct ibmvtpm_dev *)TPM_VPRIV(chip); + return NULL; + } + +@@ -83,7 +83,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) + u16 len; + int sig; + +- ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; ++ ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); + + if (!ibmvtpm->rtce_buf) { + dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); +@@ -98,7 +98,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) + + if (count < len) { + dev_err(ibmvtpm->dev, +- "Invalid size in recv: count=%ld, crq_size=%d\n", ++ "Invalid size in recv: count=%zd, crq_size=%d\n", + count, len); + return -EIO; + } +@@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + u64 *word = (u64 *) &crq; + int rc; + +- ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; ++ ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); + + if (!ibmvtpm->rtce_buf) { + dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); +@@ -136,7 +136,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + + if (count > ibmvtpm->rtce_size) { + dev_err(ibmvtpm->dev, +- "Invalid size in send: count=%ld, rtce_size=%d\n", ++ "Invalid size in send: count=%zd, rtce_size=%d\n", + count, ibmvtpm->rtce_size); + return -EIO; + } +@@ -398,6 +398,11 @@ static int tpm_ibmvtpm_resume(struct device *dev) + return rc; + } + ++static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status) ++{ ++ return (status == 0); ++} ++ + static const struct file_operations ibmvtpm_ops = { + .owner = THIS_MODULE, + .llseek = no_llseek, +@@ -414,7 +419,7 @@ static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); + static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); + static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, + NULL); +-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); ++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); + static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); + static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL); + static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); +@@ -441,7 +446,7 @@ static const struct tpm_vendor_specific tpm_ibmvtpm = { + .status = tpm_ibmvtpm_status, + .req_complete_mask = 0, + .req_complete_val = 0, +- .req_canceled = 0, ++ .req_canceled = tpm_ibmvtpm_req_canceled, + .attr_group = &ibmvtpm_attr_grp, + .miscdev = { .fops = &ibmvtpm_ops, }, + }; +@@ -647,7 +652,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, + + ibmvtpm->dev = dev; + ibmvtpm->vdev = vio_dev; +- chip->vendor.data = (void *)ibmvtpm; ++ TPM_VPRIV(chip) = (void *)ibmvtpm; + + spin_lock_init(&ibmvtpm->rtce_lock); + +diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c +index 640c9a4..770c46f 100644 +--- a/drivers/char/tpm/tpm_nsc.c ++++ b/drivers/char/tpm/tpm_nsc.c +@@ -227,6 +227,11 @@ static u8 tpm_nsc_status(struct tpm_chip *chip) + return inb(chip->vendor.base + NSC_STATUS); + } + ++static bool tpm_nsc_req_canceled(struct tpm_chip *chip, u8 status) ++{ ++ return (status == NSC_STATUS_RDY); ++} ++ + static const struct file_operations nsc_ops = { + .owner = THIS_MODULE, + .llseek = no_llseek, +@@ -258,7 +263,7 @@ static const struct tpm_vendor_specific tpm_nsc = { + .status = tpm_nsc_status, + .req_complete_mask = NSC_STATUS_OBF, + .req_complete_val = NSC_STATUS_OBF, +- .req_canceled = NSC_STATUS_RDY, ++ .req_canceled = tpm_nsc_req_canceled, + .attr_group = &nsc_attr_grp, + .miscdev = { .fops = &nsc_ops, }, + }; +diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c +index 720ebcf..2db4419 100644 +--- a/drivers/char/tpm/tpm_ppi.c ++++ b/drivers/char/tpm/tpm_ppi.c +@@ -27,15 +27,18 @@ static char *tpm_device_name = "TPM"; + static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context, + void **return_value) + { +- acpi_status status; ++ acpi_status status = AE_OK; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; +- status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); +- if (strstr(buffer.pointer, context) != NULL) { +- *return_value = handle; ++ ++ if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) { ++ if (strstr(buffer.pointer, context) != NULL) { ++ *return_value = handle; ++ status = AE_CTRL_TERMINATE; ++ } + kfree(buffer.pointer); +- return AE_CTRL_TERMINATE; + } +- return AE_OK; ++ ++ return status; + } + + static inline void ppi_assign_params(union acpi_object params[4], +@@ -158,9 +161,9 @@ static ssize_t tpm_store_ppi_request(struct device *dev, + ACPI_TYPE_STRING); + if (ACPI_FAILURE(status)) + return -ENOMEM; +- strncpy(version, ++ strlcpy(version, + ((union acpi_object *)output.pointer)->string.pointer, +- PPI_VERSION_LEN); ++ PPI_VERSION_LEN + 1); + kfree(output.pointer); + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; +@@ -169,7 +172,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev, + * is updated with function index from SUBREQ to SUBREQ2 since PPI + * version 1.1 + */ +- if (strcmp(version, "1.1") == -1) ++ if (strcmp(version, "1.1") < 0) + params[2].integer.value = TPM_PPI_FN_SUBREQ; + else + params[2].integer.value = TPM_PPI_FN_SUBREQ2; +@@ -179,7 +182,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev, + * string/package type. For PPI version 1.0 and 1.1, use buffer type + * for compatibility, and use package type since 1.2 according to spec. + */ +- if (strcmp(version, "1.2") == -1) { ++ if (strcmp(version, "1.2") < 0) { + params[3].type = ACPI_TYPE_BUFFER; + params[3].buffer.length = sizeof(req); + sscanf(buf, "%d", &req); +@@ -237,15 +240,15 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, + ACPI_TYPE_STRING); + if (ACPI_FAILURE(status)) + return -ENOMEM; +- strncpy(version, ++ strlcpy(version, + ((union acpi_object *)output.pointer)->string.pointer, +- PPI_VERSION_LEN); ++ PPI_VERSION_LEN + 1); + /* + * PPI spec defines params[3].type as empty package, but some platforms + * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for + * compatibility, define params[3].type as buffer, if PPI version < 1.2 + */ +- if (strcmp(version, "1.2") == -1) { ++ if (strcmp(version, "1.2") < 0) { + params[3].type = ACPI_TYPE_BUFFER; + params[3].buffer.length = 0; + params[3].buffer.pointer = NULL; +@@ -351,7 +354,7 @@ cleanup: + static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) + { + char *str = buf; +- char version[PPI_VERSION_LEN]; ++ char version[PPI_VERSION_LEN + 1]; + acpi_handle handle; + acpi_status status; + struct acpi_object_list input; +@@ -381,13 +384,13 @@ static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) + if (ACPI_FAILURE(status)) + return -ENOMEM; + +- strncpy(version, ++ strlcpy(version, + ((union acpi_object *)output.pointer)->string.pointer, +- PPI_VERSION_LEN); ++ PPI_VERSION_LEN + 1); + kfree(output.pointer); + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; +- if (strcmp(version, "1.2") == -1) ++ if (strcmp(version, "1.2") < 0) + return -EPERM; + + params[2].integer.value = TPM_PPI_FN_GETOPR; +@@ -452,12 +455,8 @@ int tpm_add_ppi(struct kobject *parent) + { + return sysfs_create_group(parent, &ppi_attr_grp); + } +-EXPORT_SYMBOL_GPL(tpm_add_ppi); + + void tpm_remove_ppi(struct kobject *parent) + { + sysfs_remove_group(parent, &ppi_attr_grp); + } +-EXPORT_SYMBOL_GPL(tpm_remove_ppi); +- +-MODULE_LICENSE("GPL"); +diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c +index ea31daf..1b74459 100644 +--- a/drivers/char/tpm/tpm_tis.c ++++ b/drivers/char/tpm/tpm_tis.c +@@ -84,6 +84,9 @@ static int is_itpm(struct pnp_dev *dev) + struct acpi_device *acpi = pnp_acpi_device(dev); + struct acpi_hardware_id *id; + ++ if (!acpi) ++ return 0; ++ + list_for_each_entry(id, &acpi->pnp.ids, list) { + if (!strcmp("INTC0102", id->id)) + return 1; +@@ -98,6 +101,22 @@ static inline int is_itpm(struct pnp_dev *dev) + } + #endif + ++/* Before we attempt to access the TPM we must see that the valid bit is set. ++ * The specification says that this bit is 0 at reset and remains 0 until the ++ * 'TPM has gone through its self test and initialization and has established ++ * correct values in the other bits.' */ ++static int wait_startup(struct tpm_chip *chip, int l) ++{ ++ unsigned long stop = jiffies + chip->vendor.timeout_a; ++ do { ++ if (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & ++ TPM_ACCESS_VALID) ++ return 0; ++ msleep(TPM_TIMEOUT); ++ } while (time_before(jiffies, stop)); ++ return -1; ++} ++ + static int check_locality(struct tpm_chip *chip, int l) + { + if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & +@@ -198,7 +217,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) + wait_for_tpm_stat(chip, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + chip->vendor.timeout_c, +- &chip->vendor.read_queue) ++ &chip->vendor.read_queue, true) + == 0) { + burstcnt = get_burstcount(chip); + for (; burstcnt > 0 && size < count; burstcnt--) +@@ -241,7 +260,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) + } + + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, +- &chip->vendor.int_queue); ++ &chip->vendor.int_queue, false); + status = tpm_tis_status(chip); + if (status & TPM_STS_DATA_AVAIL) { /* retry? */ + dev_err(chip->dev, "Error left over data\n"); +@@ -277,7 +296,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) + tpm_tis_ready(chip); + if (wait_for_tpm_stat + (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, +- &chip->vendor.int_queue) < 0) { ++ &chip->vendor.int_queue, false) < 0) { + rc = -ETIME; + goto out_err; + } +@@ -292,7 +311,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) + } + + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, +- &chip->vendor.int_queue); ++ &chip->vendor.int_queue, false); + status = tpm_tis_status(chip); + if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { + rc = -EIO; +@@ -304,7 +323,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) + iowrite8(buf[count], + chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, +- &chip->vendor.int_queue); ++ &chip->vendor.int_queue, false); + status = tpm_tis_status(chip); + if ((status & TPM_STS_DATA_EXPECT) != 0) { + rc = -EIO; +@@ -342,7 +361,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) + if (wait_for_tpm_stat + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, + tpm_calc_ordinal_duration(chip, ordinal), +- &chip->vendor.read_queue) < 0) { ++ &chip->vendor.read_queue, false) < 0) { + rc = -ETIME; + goto out_err; + } +@@ -374,7 +393,7 @@ static int probe_itpm(struct tpm_chip *chip) + if (vendor != TPM_VID_INTEL) + return 0; + +- itpm = 0; ++ itpm = false; + + rc = tpm_tis_send_data(chip, cmd_getticks, len); + if (rc == 0) +@@ -383,7 +402,7 @@ static int probe_itpm(struct tpm_chip *chip) + tpm_tis_ready(chip); + release_locality(chip, chip->vendor.locality, 0); + +- itpm = 1; ++ itpm = true; + + rc = tpm_tis_send_data(chip, cmd_getticks, len); + if (rc == 0) { +@@ -400,6 +419,19 @@ out: + return rc; + } + ++static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status) ++{ ++ switch (chip->vendor.manufacturer_id) { ++ case TPM_VID_WINBOND: ++ return ((status == TPM_STS_VALID) || ++ (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY))); ++ case TPM_VID_STM: ++ return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)); ++ default: ++ return (status == TPM_STS_COMMAND_READY); ++ } ++} ++ + static const struct file_operations tis_ops = { + .owner = THIS_MODULE, + .llseek = no_llseek, +@@ -416,7 +448,7 @@ static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); + static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); + static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, + NULL); +-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); ++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); + static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); + static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL); + static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); +@@ -445,7 +477,7 @@ static struct tpm_vendor_specific tpm_tis = { + .cancel = tpm_tis_ready, + .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, +- .req_canceled = TPM_STS_COMMAND_READY, ++ .req_canceled = tpm_tis_req_canceled, + .attr_group = &tis_attr_grp, + .miscdev = { + .fops = &tis_ops,}, +@@ -502,7 +534,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) + return IRQ_HANDLED; + } + +-static bool interrupts = 1; ++static bool interrupts = true; + module_param(interrupts, bool, 0444); + MODULE_PARM_DESC(interrupts, "Enable interrupts"); + +@@ -528,12 +560,18 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + ++ if (wait_startup(chip, 0) != 0) { ++ rc = -ENODEV; ++ goto out_err; ++ } ++ + if (request_locality(chip, 0) != 0) { + rc = -ENODEV; + goto out_err; + } + + vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); ++ chip->vendor.manufacturer_id = vendor; + + dev_info(dev, + "1.2 TPM (device-id 0x%X, rev-id %d)\n", +@@ -545,7 +583,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + rc = -ENODEV; + goto out_err; + } +- itpm = (probe == 0) ? 0 : 1; ++ itpm = !!probe; + } + + if (itpm) +@@ -728,6 +766,25 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) + } + #endif + ++#ifdef CONFIG_PM_SLEEP ++static int tpm_tis_resume(struct device *dev) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ int ret; ++ ++ if (chip->vendor.irq) ++ tpm_tis_reenable_interrupts(chip); ++ ++ ret = tpm_pm_resume(dev); ++ if (!ret) ++ tpm_do_selftest(chip); ++ ++ return ret; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); ++ + #ifdef CONFIG_PNP + static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, + const struct pnp_device_id *pnp_id) +@@ -741,34 +798,14 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, + if (pnp_irq_valid(pnp_dev, 0)) + irq = pnp_irq(pnp_dev, 0); + else +- interrupts = 0; ++ interrupts = false; + + if (is_itpm(pnp_dev)) +- itpm = 1; ++ itpm = true; + + return tpm_tis_init(&pnp_dev->dev, start, len, irq); + } + +-static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) +-{ +- return tpm_pm_suspend(&dev->dev); +-} +- +-static int tpm_tis_pnp_resume(struct pnp_dev *dev) +-{ +- struct tpm_chip *chip = pnp_get_drvdata(dev); +- int ret; +- +- if (chip->vendor.irq) +- tpm_tis_reenable_interrupts(chip); +- +- ret = tpm_pm_resume(&dev->dev); +- if (!ret) +- tpm_do_selftest(chip); +- +- return ret; +-} +- + static struct pnp_device_id tpm_pnp_tbl[] = { + {"PNP0C31", 0}, /* TPM */ + {"ATM1200", 0}, /* Atmel */ +@@ -797,9 +834,12 @@ static struct pnp_driver tis_pnp_driver = { + .name = "tpm_tis", + .id_table = tpm_pnp_tbl, + .probe = tpm_tis_pnp_init, +- .suspend = tpm_tis_pnp_suspend, +- .resume = tpm_tis_pnp_resume, + .remove = tpm_tis_pnp_remove, ++#ifdef CONFIG_PM_SLEEP ++ .driver = { ++ .pm = &tpm_tis_pm, ++ }, ++#endif + }; + + #define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 +@@ -808,20 +848,6 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, + MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); + #endif + +-#ifdef CONFIG_PM_SLEEP +-static int tpm_tis_resume(struct device *dev) +-{ +- struct tpm_chip *chip = dev_get_drvdata(dev); +- +- if (chip->vendor.irq) +- tpm_tis_reenable_interrupts(chip); +- +- return tpm_pm_resume(dev); +-} +-#endif +- +-static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); +- + static struct platform_driver tis_drv = { + .driver = { + .name = "tpm_tis", +@@ -846,12 +872,19 @@ static int __init init_tis(void) + rc = platform_driver_register(&tis_drv); + if (rc < 0) + return rc; +- if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) +- return PTR_ERR(pdev); +- if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { +- platform_device_unregister(pdev); +- platform_driver_unregister(&tis_drv); ++ pdev = platform_device_register_simple("tpm_tis", -1, NULL, 0); ++ if (IS_ERR(pdev)) { ++ rc = PTR_ERR(pdev); ++ goto err_dev; + } ++ rc = tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0); ++ if (rc) ++ goto err_init; ++ return 0; ++err_init: ++ platform_device_unregister(pdev); ++err_dev: ++ platform_driver_unregister(&tis_drv); + return rc; + } + +diff --git a/include/linux/tpm.h b/include/linux/tpm.h +index fcb627f..9a9051b 100644 +--- a/include/linux/tpm.h ++++ b/include/linux/tpm.h +@@ -22,6 +22,8 @@ + #ifndef __LINUX_TPM_H__ + #define __LINUX_TPM_H__ + ++#define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ ++ + /* + * Chip num is this value or a valid tpm idx + */ +-- +1.9.1 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/beaglebone/defconfig b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/beaglebone/defconfig index f6b22481..23e0bf7a 100644 --- a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/beaglebone/defconfig +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/beaglebone/defconfig @@ -1309,6 +1309,7 @@ CONFIG_BMP085_I2C=m # CONFIG_USB_SWITCH_FSA9480 is not set CONFIG_GPEVT=y CONFIG_GROVE_I2C=y +CONFIG_TIEQEP=y # CONFIG_C2PORT is not set # @@ -1336,7 +1337,9 @@ CONFIG_BEAGLEBONE_PINMUX_HELPER=y CONFIG_BEAGLEBONE_IIO_HELPER=y CONFIG_CAPE_BEAGLEBONE=y CONFIG_CAPE_BEAGLEBONE_GEIGER=y +CONFIG_CAPE_BEAGLEBONE_ARGUS=y CONFIG_CAPE_BEAGLEBONE_NIXIE=y +CONFIG_CAPE_LOGIBONE_R1=y # # SCSI device support @@ -1849,9 +1852,13 @@ CONFIG_HW_RANDOM=y # CONFIG_HW_RANDOM_ATMEL is not set CONFIG_HW_RANDOM_VIRTIO=m # CONFIG_HW_RANDOM_EXYNOS is not set +CONFIG_HW_RANDOM_TPM=m # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS_I2C_ATMEL=m +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_TCG_ATMEL is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y @@ -2096,6 +2103,7 @@ CONFIG_SENSORS_AM335X_BANDGAP=y # CONFIG_SENSORS_GL520SM is not set CONFIG_SENSORS_GPIO_FAN=m CONFIG_SENSORS_HIH6130=m +CONFIG_SENSORS_HTU21=m # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_JC42 is not set # CONFIG_SENSORS_LINEAGE is not set @@ -2612,6 +2620,7 @@ CONFIG_VIDEO_MT9V011=m # CONFIG_SOC_CAMERA_IMX074 is not set CONFIG_SOC_CAMERA_MT9M001=y CONFIG_SOC_CAMERA_MT9M111=y +CONFIG_SOC_CAMERA_MT9M114=y CONFIG_SOC_CAMERA_MT9T031=y CONFIG_SOC_CAMERA_MT9T112=y CONFIG_SOC_CAMERA_MT9V022=y @@ -4131,6 +4140,7 @@ CONFIG_EARLY_PRINTK=y # Security options # CONFIG_KEYS=y +# CONFIG_TRUSTED_KEYS is not set # CONFIG_ENCRYPTED_KEYS is not set # CONFIG_KEYS_DEBUG_PROC_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0018-beaglebone-capes-add-replicape-A2-and-A3-support.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0018-beaglebone-capes-add-replicape-A2-and-A3-support.patch new file mode 100644 index 00000000..51606c52 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0018-beaglebone-capes-add-replicape-A2-and-A3-support.patch @@ -0,0 +1,586 @@ +From 96593cf8ac3870ba622ca26b64b49233065e324c Mon Sep 17 00:00:00 2001 +From: Koen Kooi +Date: Mon, 9 Sep 2013 14:24:49 +0200 +Subject: [PATCH 18/18] beaglebone capes: add replicape A2 and A3 support + +Signed-off-by: Koen Kooi +--- + firmware/Makefile | 4 +- + firmware/capes/cape-bone-replicape-00A2.dts | 251 ++++++++++++++++++++++++ + firmware/capes/cape-bone-replicape-00A3.dts | 291 ++++++++++++++++++++++++++++ + 3 files changed, 545 insertions(+), 1 deletion(-) + create mode 100644 firmware/capes/cape-bone-replicape-00A2.dts + create mode 100644 firmware/capes/cape-bone-replicape-00A3.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index b93c558..bff3bb1 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -194,7 +194,9 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + BB-BONE-BACON-00A0.dtbo \ + BB-BONE-BACONE-00A0.dtbo \ + BB-BONE-BACONE2-00A0.dtbo \ +- DNIL-AMPCAPE-1-00R1.dtbo ++ DNIL-AMPCAPE-1-00R1.dtbo \ ++ cape-bone-replicape-00A2.dtbo \ ++ cape-bone-replicape-00A3.dtbo + + # the geiger cape + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \ +diff --git a/firmware/capes/cape-bone-replicape-00A2.dts b/firmware/capes/cape-bone-replicape-00A2.dts +new file mode 100644 +index 0000000..ca53b3b +--- /dev/null ++++ b/firmware/capes/cape-bone-replicape-00A2.dts +@@ -0,0 +1,251 @@ ++/* ++ * Copyright (C) 2013 Intelligent Agent AS ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-REPLICAP"; ++ version = "00A2"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header P8 uses */ ++ "P8.16", /* (3) DIR_EXT_2 */ ++ "P8.15", /* (4) DIR_EXT_1 */ ++ "P8.14", /* (5) DIR_Z */ ++ "P8.17", /* (6) STEP_X */ ++ "P8.7", /* END_STOP_Y1 */ ++ "P8.8", /* FAULT_EXT_2 */ ++ "P8.9", /* FAULT_Y */ ++ "P8.10", /* FAULT_x */ ++ "P8.18", /* FAULT_EXT_1 */ ++ "P8.11", /* (22) STEP_EXT_2 */ ++ "P8.12", /* (23) STEP_Y */ ++ "P8.13", /* (24) STEP_Z */ ++ "P8.19", /* (25) DIR_Y */ ++ "P8.26", /* DIR_X */ ++ /* the pin header P9 uses */ ++ "P9.11", /* END_STOP_Z1 */ ++ "P9.12", /* STEP_EXT_1 */ ++ "P9.13", /* END_STOP_X2 */ ++ "P9.18", /* END_STOP_Z2 */ ++ "P9.24", /* FAULT_Z */ ++ "P9.25", /* END_STOP_Y2 */ ++ "P9.26", /* END_STOP_X1 */ ++ "P9.28", /* SPI1_CS0 */ ++ "P9.29", /* SPI1_MISO */ ++ "P9.30", /* SPI1_MOSI */ ++ "P9.31", /* SPI1_SCLK */ ++ "P9.33", /* AIN4 */ ++ "P9.35", /* AIN6 */ ++ "P9.36", /* AIN5 */ ++ "P9.42", /* SPI1_CS1 */ ++ /* Hardware IP cores in use */ ++ "spi1", ++ "pruss"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { ++ pinctrl-single,pins = < ++ 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ ++ 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ ++ 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ ++ 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ ++ 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ ++ >; ++ }; ++ pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ ++ pinctrl-single,pins = < ++ 0x038 0x07 // P8_16 (3) = DIR_EXT_2 = GPIO1_14 ++ 0x03C 0x07 // P8_15 (4) = DIR_EXT_1 = GPIO1_15 ++ 0x028 0x07 // P8_14 (5) = DIR_Z = GPIO0_26 ++ 0x02C 0x07 // P8_17 (6) = STEP_X = GPIO0_27 ++ 0x034 0x07 // P8_11 (22) = step_ext_2 = GPIO1_13 ++ 0x030 0x07 // P8_12 (23) = Step_y = GPIO1_12 ++ 0x024 0x07 // P8_13 (24) = Step_z = GPIO0_23 ++ 0x020 0x07 // P8_19 (25) = Dir_y = GPIO0_22 ++ 0x07C 0x07 // P8_26 = Dir_x = GPIO1_29 ++ 0x078 0x07 // P9_12 = step ext 1 = GPIO1_28 ++ >; ++ }; ++ ++ stepper_fault_pins: pinmux_stepper_fault_pins{ ++ pinctrl-single,pins = < ++ 0x094 0x37 // P8_8 = Fault Ext 2 = GPIO2_2 gpmc_oen_ren.gpio2[3] ++ 0x09C 0x37 // P8_9 = FAYLT Y = GPIO2_5 ++ 0x098 0x37 // P8_10 = FAULT X = GPIO2_4 gpmc_wen.gpio2[4] ++ 0x08C 0x37 // P8_18 = Fault_ext 1 = GPIO2_1 ++ 0x184 0x37 // P9_24 = Fault Z = GPIO0_15 ++ >; ++ }; ++ ++ end_stop_pins: pinmux_end_stop_pins{ ++ pinctrl-single,pins = < ++ 0x090 0x37 // P8_7 = End stop X1 = GPIO2_2 ++ 0x070 0x37 // P9_11 = End stop Y1 = GPIO0_30 ++ 0x074 0x37 // P9_13 = End stop Z1 = GPIO0_31 ++ 0x158 0x37 // P9_18 = End stop Z2 = GPIO0_4 ++ 0x1AC 0x37 // P9_25 = End stop Y2 = GPIO3_21 ++ 0x180 0x37 // P9_26 = End stop X2 = GPIO0_14 ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bone_replicape_spi1_pins>; ++ cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; ++ ++ stepper_control{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; // Stepper control has mode 1 (CPOL = 0, CPHA = 1) ++ }; ++ ++ stepper_current{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ // Stepper current has mode 0 (CPOL = 0, CPHA = 0) ++ }; ++ }; ++ }; ++ ++ fragment@2{ ++ target = <&pruss>; ++ __overlay__{ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pruicss_stepper_pins>; ++ ++ stepper_x{ ++ pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; ++ gpios = <&gpio1 27 0 ++ &gpio2 29 0>; ++ }; ++ stepper_y{ ++ pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; ++ gpios =<&gpio2 12 0 ++ &gpio1 22 0>; ++ }; ++ stepper_z{ ++ pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; ++ gpios = <&gpio1 23 0 ++ &gpio1 26 0>; ++ }; ++ stepper_ext_1{ ++ pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; ++ gpios = <&gpio2 28 0 ++ &gpio2 15 0>; ++ }; ++ stepper_ext_2{ ++ pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; ++ gpios = <&gpio2 13 0 ++ &gpio2 14 0>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ocp>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ tsc { ++ ti,wires = <4>; ++ }; ++ adc { ++ ti,adc-channels = <4>; ++ }; ++ }; ++ ++ thermistors{ ++ compatible = "bone-iio-helper"; ++ vsense-name = "AIN4", "AIN5", "AIN6", "AIN7"; ++ vsense-scale = <100 100 100 100 >; ++ status = "okay"; ++ }; ++ gpio_keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&end_stop_pins>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch_x1 { ++ label = "End-stop-X1"; ++ debounce_interval = <50>; ++ linux,code = <1>; ++ gpios = <&gpio3 2 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_x2 { ++ label = "End-stop-X2"; ++ debounce_interval = <50>; ++ linux,code = <2>; ++ gpios = <&gpio1 14 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y1 { ++ label = "End-stop-Y1"; ++ debounce_interval = <50>; ++ linux,code = <3>; ++ gpios = <&gpio1 30 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y2 { ++ label = "End-stop-Y2"; ++ debounce_interval = <50>; ++ linux,code = <4>; ++ gpios = <&gpio4 21 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z1 { ++ label = "End-stop-Z1"; ++ debounce_interval = <50>; ++ linux,code = <5>; ++ gpios = <&gpio1 31 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z2 { ++ label = "End-stop-Z2"; ++ debounce_interval = <50>; ++ linux,code = <6>; ++ gpios = <&gpio1 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ }; ++ }; ++ }; ++}; +diff --git a/firmware/capes/cape-bone-replicape-00A3.dts b/firmware/capes/cape-bone-replicape-00A3.dts +new file mode 100644 +index 0000000..76253d6 +--- /dev/null ++++ b/firmware/capes/cape-bone-replicape-00A3.dts +@@ -0,0 +1,291 @@ ++/* ++ * Copyright (C) 2013 Intelligent Agent AS ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-REPLICAP"; ++ version = "00A3"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header P8 uses */ ++ "P8.16", /* (3) DIR_EXT_2 */ ++ "P8.15", /* (4) DIR_EXT_1 */ ++ "P8.14", /* (5) DIR_Z */ ++ "P8.17", /* (6) STEP_X */ ++ "P8.7", /* END_STOP_Y1 */ ++ "P8.8", /* FAULT_EXT_2 */ ++ "P8.9", /* FAULT_Y */ ++ "P8.10", /* FAULT_x */ ++ "P8.18", /* FAULT_EXT_1 */ ++ "P8.11", /* (22) STEP_EXT_2 */ ++ "P8.12", /* (23) STEP_Y */ ++ "P8.13", /* (24) STEP_Z */ ++ "P8.19", /* (25) DIR_Y */ ++ "P8.26", /* DIR_X */ ++ /* the pin header P9 uses */ ++ "P9.11", /* END_STOP_Z1 */ ++ "P9.12", /* STEP_EXT_1 */ ++ "P9.13", /* END_STOP_X2 */ ++ "P9.18", /* END_STOP_Z2 */ ++ "P9.22", /* Dallas 1W */ ++ "P9.24", /* FAULT_Z */ ++ "P9.25", /* END_STOP_Y2 */ ++ "P9.26", /* END_STOP_X1 */ ++ "P9.28", /* SPI1_CS0 */ ++ "P9.29", /* SPI1_MISO */ ++ "P9.30", /* SPI1_MOSI */ ++ "P9.31", /* SPI1_SCLK */ ++ "P9.33", /* AIN4 */ ++ "P9.35", /* AIN6 */ ++ "P9.36", /* AIN5 */ ++ "P9.42", /* SPI1_CS1 */ ++ /* Hardware IP cores in use */ ++ "spi1", ++ "pruss"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { ++ pinctrl-single,pins = < ++ 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ ++ 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ ++ 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ ++ 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ ++ 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ ++ >; ++ }; ++ pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ ++ pinctrl-single,pins = < ++ 0x038 0x07 // P8_16 (3) = DIR_EXT_2 = GPIO1_14 ++ 0x03C 0x07 // P8_15 (4) = DIR_EXT_1 = GPIO1_15 ++ 0x028 0x07 // P8_14 (5) = DIR_Z = GPIO0_26 ++ 0x02C 0x07 // P8_17 (6) = STEP_X = GPIO0_27 ++ 0x034 0x07 // P8_11 (22) = step_ext_2 = GPIO1_13 ++ 0x030 0x07 // P8_12 (23) = Step_y = GPIO1_12 ++ 0x024 0x07 // P8_13 (24) = Step_z = GPIO0_23 ++ 0x020 0x07 // P8_19 (25) = Dir_y = GPIO0_22 ++ 0x07C 0x07 // P8_26 = Dir_x = GPIO1_29 ++ 0x078 0x07 // P9_12 = step ext 1 = GPIO1_28 ++ >; ++ }; ++ ++ stepper_fault_pins: pinmux_stepper_fault_pins{ ++ pinctrl-single,pins = < ++ 0x094 0x37 // P8_8 = Fault Ext 2 = GPIO2_3 gpmc_oen_ren.gpio2[3] ++ 0x09C 0x37 // P8_9 = FAYLT Y = GPIO2_5 ++ 0x098 0x37 // P8_10 = FAULT X = GPIO2_4 gpmc_wen.gpio2[4] ++ 0x08C 0x37 // P8_18 = Fault_ext 1 = GPIO2_1 ++ 0x184 0x37 // P9_24 = Fault Z = GPIO0_15 ++ >; ++ }; ++ ++ end_stop_pins: pinmux_end_stop_pins{ ++ pinctrl-single,pins = < ++ 0x090 0x37 // P8_7 = End stop X1 = GPIO2_2 ++ 0x070 0x37 // P9_11 = End stop Y1 = GPIO0_30 ++ 0x074 0x37 // P9_13 = End stop Z1 = GPIO0_31 ++ 0x158 0x37 // P9_18 = End stop Z2 = GPIO0_4 ++ 0x1AC 0x37 // P9_25 = End stop Y2 = GPIO3_21 ++ 0x180 0x37 // P9_26 = End stop X2 = GPIO0_14 ++ >; ++ }; ++ dallas_w1_pins: pinmux_dallas_w1_pins { ++ pinctrl-single,pins = < ++ 0x150 0x37 // Dallas 1W ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bone_replicape_spi1_pins>; ++ cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; ++ ++ stepper_control{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; // Stepper control has mode 1 (CPOL = 0, CPHA = 1) ++ }; ++ ++ stepper_current{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ // Stepper current has mode 0 (CPOL = 0, CPHA = 0) ++ }; ++ }; ++ }; ++ ++ fragment@2{ ++ target = <&pruss>; ++ __overlay__{ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pruicss_stepper_pins>; ++ ++ stepper_x{ ++ pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; ++ gpios = <&gpio1 27 0 ++ &gpio2 29 0>; ++ }; ++ stepper_y{ ++ pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; ++ gpios =<&gpio2 12 0 ++ &gpio1 22 0>; ++ }; ++ stepper_z{ ++ pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; ++ gpios = <&gpio1 23 0 ++ &gpio1 26 0>; ++ }; ++ stepper_ext_1{ ++ pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; ++ gpios = <&gpio2 28 0 ++ &gpio2 15 0>; ++ }; ++ stepper_ext_2{ ++ pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; ++ gpios = <&gpio2 13 0 ++ &gpio2 14 0>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ocp>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ adc { ++ ti,adc-channels = <4 5 6 7>; ++ }; ++ }; ++ ++ gpio_keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&end_stop_pins>; ++ pinctrl-1 = <&stepper_fault_pins>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch_x1 { ++ label = "End-stop-X1"; ++ debounce_interval = <50>; ++ linux,code = <1>; ++ gpios = <&gpio3 2 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_x2 { ++ label = "End-stop-X2"; ++ debounce_interval = <50>; ++ linux,code = <2>; ++ gpios = <&gpio1 14 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y1 { ++ label = "End-stop-Y1"; ++ debounce_interval = <50>; ++ linux,code = <3>; ++ gpios = <&gpio1 30 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y2 { ++ label = "End-stop-Y2"; ++ debounce_interval = <50>; ++ linux,code = <4>; ++ gpios = <&gpio4 21 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z1 { ++ label = "End-stop-Z1"; ++ debounce_interval = <50>; ++ linux,code = <5>; ++ gpios = <&gpio1 31 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z2 { ++ label = "End-stop-Z2"; ++ debounce_interval = <50>; ++ linux,code = <6>; ++ gpios = <&gpio1 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_x { ++ label = "Fault-X"; ++ debounce_interval = <50>; ++ linux,code = <7>; ++ gpios = <&gpio3 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_y { ++ label = "Fault-Y"; ++ debounce_interval = <50>; ++ linux,code = <8>; ++ gpios = <&gpio3 5 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_z { ++ label = "Fault-Z"; ++ debounce_interval = <50>; ++ linux,code = <9>; ++ gpios = <&gpio1 15 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext_1 { ++ label = "Fault-Ext-1"; ++ debounce_interval = <50>; ++ linux,code = <10>; ++ gpios = <&gpio3 1 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext_2 { ++ label = "Fault-Ext-2"; ++ debounce_interval = <50>; ++ linux,code = <11>; ++ gpios = <&gpio3 3 0x5>; ++ gpio-key,wakeup; ++ }; ++ }; ++ onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dallas_w1_pins>; ++ status = "okay"; ++ gpios = <&gpio1 2 0>; ++ }; ++ }; ++ }; ++}; +-- +1.8.2.1 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0019-Added-camera-cape-support-for-Beaglebone-Black.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0019-Added-camera-cape-support-for-Beaglebone-Black.patch new file mode 100644 index 00000000..76344e0d --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0019-Added-camera-cape-support-for-Beaglebone-Black.patch @@ -0,0 +1,1407 @@ +From 2ea6b07eb9a2e466f24d0e9bdf937fd5691aea6c Mon Sep 17 00:00:00 2001 +From: vvdn +Date: Sat, 23 Nov 2013 08:24:37 -0500 +Subject: [PATCH 19/19] Added camera cape support for Beaglebone Black + +--- + drivers/media/i2c/soc_camera/Kconfig | 6 + + drivers/media/i2c/soc_camera/Makefile | 1 + + drivers/media/i2c/soc_camera/mt9m114.c | 1056 +++++++++++++++++++++++ + drivers/media/platform/soc_camera/cssp_camera.c | 15 + + firmware/Makefile | 1 + + firmware/capes/BB-BONE-CAM-VVDN-00A0.dts | 230 +++++ + include/media/v4l2-chip-ident.h | 1 + + 7 files changed, 1310 insertions(+) + create mode 100644 drivers/media/i2c/soc_camera/mt9m114.c + create mode 100644 firmware/capes/BB-BONE-CAM-VVDN-00A0.dts + +diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig +index 6dff2b7..de56e5a 100644 +--- a/drivers/media/i2c/soc_camera/Kconfig ++++ b/drivers/media/i2c/soc_camera/Kconfig +@@ -21,6 +21,12 @@ config SOC_CAMERA_MT9M111 + This driver supports MT9M111, MT9M112 and MT9M131 cameras from + Micron/Aptina + ++config SOC_CAMERA_MT9M114 ++ tristate "Aptina MT9M114 sensor support" ++ depends on VIDEO_V4L2 && I2C ++ ---help--- ++ This driver supports MT9TM114 cameras from Aptina. ++ + config SOC_CAMERA_MT9T031 + tristate "mt9t031 support" + depends on SOC_CAMERA && I2C +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index d0421fe..664fbb0 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -1,6 +1,7 @@ + obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o + obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o + obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o ++obj-$(CONFIG_SOC_CAMERA_MT9M114) += mt9m114.o + obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o + obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o + obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o +diff --git a/drivers/media/i2c/soc_camera/mt9m114.c b/drivers/media/i2c/soc_camera/mt9m114.c +new file mode 100644 +index 0000000..6eab204 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/mt9m114.c +@@ -0,0 +1,1056 @@ ++/* ++ * mt9m114.c Aptina MT9M114 sensor driver ++ * ++ * Copyright (c) 2013 VVDN Technologies ++ * Copyright (c) 2012 Analog Devices Inc. ++ * ++ * refer to: SoC Camera driver by Andrew Chew ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* Sysctl registers */ ++#define MT9M114_CHIP_ID 0x0000 ++#define MT9M114_COMMAND_REGISTER 0x0080 ++#define MT9M114_COMMAND_REGISTER_APPLY_PATCH (1 << 0) ++#define MT9M114_COMMAND_REGISTER_SET_STATE (1 << 1) ++#define MT9M114_COMMAND_REGISTER_REFRESH (1 << 2) ++#define MT9M114_COMMAND_REGISTER_WAIT_FOR_EVENT (1 << 3) ++#define MT9M114_COMMAND_REGISTER_OK (1 << 15) ++#define MT9M114_SOFT_RESET 0x001a ++#define MT9M114_PAD_SLEW 0x001e ++#define MT9M114_PAD_CONTROL 0x0032 ++ ++/* XDMA registers */ ++#define MT9M114_ACCESS_CTL_STAT 0x0982 ++#define MT9M114_PHYSICAL_ADDRESS_ACCESS 0x098a ++#define MT9M114_LOGICAL_ADDRESS_ACCESS 0x098e ++ ++/* Core registers */ ++#define MT9M114_RESET_REGISTER 0x301a ++#define MT9M114_FLASH 0x3046 ++#define MT9M114_CUSTOMER_REV 0x31fe ++ ++/* Camera Control registers */ ++#define MT9M114_CAM_SENSOR_CFG_Y_ADDR_START 0xc800 ++#define MT9M114_CAM_SENSOR_CFG_X_ADDR_START 0xc802 ++#define MT9M114_CAM_SENSOR_CFG_Y_ADDR_END 0xc804 ++#define MT9M114_CAM_SENSOR_CFG_X_ADDR_END 0xc806 ++#define MT9M114_CAM_SENSOR_CFG_PIXCLK 0xc808 ++#define MT9M114_CAM_SENSOR_CFG_ROW_SPEED 0xc80c ++#define MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN 0xc80e ++#define MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX 0xc810 ++#define MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES 0xc812 ++#define MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK 0xc814 ++#define MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION 0xc816 ++#define MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW 0xc818 ++#define MT9M114_CAM_SENSOR_CFG_REG_0_DATA 0xc826 ++#define MT9M114_CAM_SENSOR_CONTROL_READ_MODE 0xc834 ++#define MT9M114_CAM_CROP_WINDOW_XOFFSET 0xc854 ++#define MT9M114_CAM_CROP_WINDOW_YOFFSET 0xc856 ++#define MT9M114_CAM_CROP_WINDOW_WIDTH 0xc858 ++#define MT9M114_CAM_CROP_WINDOW_HEIGHT 0xc85a ++#define MT9M114_CAM_CROP_CROPMODE 0xc85c ++#define MT9M114_CAM_OUTPUT_WIDTH 0xc868 ++#define MT9M114_CAM_OUTPUT_HEIGHT 0xc86a ++#define MT9M114_CAM_OUTPUT_FORMAT 0xc86c ++#define MT9M114_CAM_AET_AEMODE 0xc878 ++#define MT9M114_CAM_AET_MAX_FRAME_RATE 0xc88c ++#define MT9M114_CAM_AET_MIN_FRAME_RATE 0xc88e ++#define MT9M114_CAM_AWB_AWB_XSCALE 0xc8f2 ++#define MT9M114_CAM_AWB_AWB_YSCALE 0xc8f3 ++#define MT9M114_CAM_AWB_AWB_XSHIFT_PRE_ADJ 0xc904 ++#define MT9M114_CAM_AWB_AWB_YSHIFT_PRE_ADJ 0xc906 ++#define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART 0xc914 ++#define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART 0xc916 ++#define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND 0xc918 ++#define MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND 0xc91a ++#define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART 0xc91c ++#define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART 0xc91e ++#define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND 0xc920 ++#define MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND 0xc922 ++#define MT9M114_CAM_SYSCTL_PLL_ENABLE 0xc97e ++#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_M_N 0xc980 ++#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_P 0xc982 ++#define MT9M114_CAM_PORT_OUTPUT_CONTROL 0xc984 ++ ++/* System Manager registers */ ++#define MT9M114_SYSMGR_NEXT_STATE 0xdc00 ++#define MT9M114_SYSMGR_CURRENT_STATE 0xdc01 ++#define MT9M114_SYSMGR_CMD_STATUS 0xdc02 ++ ++/* Patch Loader registers */ ++#define MT9M114_PATCHLDR_LOADER_ADDRESS 0xe000 ++#define MT9M114_PATCHLDR_PATCH_ID 0xe002 ++#define MT9M114_PATCHLDR_FIRMWARE_ID 0xe004 ++#define MT9M114_PATCHLDR_APPLY_STATUS 0xe008 ++#define MT9M114_PATCHLDR_NUM_PATCHES 0xe009 ++#define MT9M114_PATCHLDR_PATCH_ID_0 0xe00a ++#define MT9M114_PATCHLDR_PATCH_ID_1 0xe00c ++#define MT9M114_PATCHLDR_PATCH_ID_2 0xe00e ++#define MT9M114_PATCHLDR_PATCH_ID_3 0xe010 ++#define MT9M114_PATCHLDR_PATCH_ID_4 0xe012 ++#define MT9M114_PATCHLDR_PATCH_ID_5 0xe014 ++#define MT9M114_PATCHLDR_PATCH_ID_6 0xe016 ++#define MT9M114_PATCHLDR_PATCH_ID_7 0xe018 ++ ++/* SYS_STATE values (for SYSMGR_NEXT_STATE and SYSMGR_CURRENT_STATE) */ ++#define MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE 0x28 ++#define MT9M114_SYS_STATE_STREAMING 0x31 ++#define MT9M114_SYS_STATE_START_STREAMING 0x34 ++#define MT9M114_SYS_STATE_ENTER_SUSPEND 0x40 ++#define MT9M114_SYS_STATE_SUSPENDED 0x41 ++#define MT9M114_SYS_STATE_ENTER_STANDBY 0x50 ++#define MT9M114_SYS_STATE_STANDBY 0x52 ++#define MT9M114_SYS_STATE_LEAVE_STANDBY 0x54 ++ ++/* Result status of last SET_STATE comamnd */ ++#define MT9M114_SET_STATE_RESULT_ENOERR 0x00 ++#define MT9M114_SET_STATE_RESULT_EINVAL 0x0c ++#define MT9M114_SET_STATE_RESULT_ENOSPC 0x0d ++ ++#define MAX_FRAME_RATE 30 ++ ++struct mt9m114 { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct v4l2_fract frame_rate; ++ struct v4l2_mbus_framefmt fmt; ++}; ++ ++struct mt9m114_reg { ++ u16 reg; ++ u32 val; ++ int width; ++}; ++ ++enum { ++ MT9M114_QVGA, ++ MT9M114_VGA, ++ MT9M114_WVGA, ++ MT9M114_720P, ++}; ++ ++struct mt9m114_resolution { ++ unsigned int width; ++ unsigned int height; ++}; ++ ++static const struct mt9m114_resolution mt9m114_resolutions[] = { ++ [MT9M114_QVGA] = { ++ .width = 320, ++ .height = 240, ++ }, ++ [MT9M114_VGA] = { ++ .width = 640, ++ .height = 480, ++ }, ++ [MT9M114_WVGA] = { ++ .width = 800, ++ .height = 480, ++ }, ++ [MT9M114_720P] = { ++ .width = 1280, ++ .height = 720, ++ }, ++}; ++ ++static const struct mt9m114_reg mt9m114_init[] = { ++ { MT9M114_RESET_REGISTER, 0x0218, 2 }, ++ ++ /* PLL settings */ ++ { MT9M114_LOGICAL_ADDRESS_ACCESS, 0x0000, 2 }, ++ { MT9M114_CAM_SYSCTL_PLL_ENABLE, 0x01, 1 }, ++ { MT9M114_CAM_SYSCTL_PLL_DIVIDER_M_N, 0x0118, 2 }, ++ { MT9M114_CAM_SYSCTL_PLL_DIVIDER_P, 0x0700, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_PIXCLK, 0x2DC6C00, 4 }, ++ ++ /* Sensor optimization */ ++ { 0x316A, 0x8270, 2 }, ++ { 0x316C, 0x8270, 2 }, ++ { 0x3ED0, 0x2305, 2 }, ++ { 0x3ED2, 0x77CF, 2 }, ++ { 0x316E, 0x8202, 2 }, ++ { 0x3180, 0x87FF, 2 }, ++ { 0x30D4, 0x6080, 2 }, ++ { 0xA802, 0x0008, 2 }, ++ ++ { 0x3E14, 0xFF39, 2 }, ++ ++ /* APGA */ ++ { 0xC95E, 0x0000, 2 }, ++ ++ /* Camera control module */ ++ { 0xC892, 0x0267, 2 }, ++ { 0xC894, 0xFF1A, 2 }, ++ { 0xC896, 0xFFB3, 2 }, ++ { 0xC898, 0xFF80, 2 }, ++ { 0xC89A, 0x0166, 2 }, ++ { 0xC89C, 0x0003, 2 }, ++ { 0xC89E, 0xFF9A, 2 }, ++ { 0xC8A0, 0xFEB4, 2 }, ++ { 0xC8A2, 0x024D, 2 }, ++ { 0xC8A4, 0x01BF, 2 }, ++ { 0xC8A6, 0xFF01, 2 }, ++ { 0xC8A8, 0xFFF3, 2 }, ++ { 0xC8AA, 0xFF75, 2 }, ++ { 0xC8AC, 0x0198, 2 }, ++ { 0xC8AE, 0xFFFD, 2 }, ++ { 0xC8B0, 0xFF9A, 2 }, ++ { 0xC8B2, 0xFEE7, 2 }, ++ { 0xC8B4, 0x02A8, 2 }, ++ { 0xC8B6, 0x01D9, 2 }, ++ { 0xC8B8, 0xFF26, 2 }, ++ { 0xC8BA, 0xFFF3, 2 }, ++ { 0xC8BC, 0xFFB3, 2 }, ++ { 0xC8BE, 0x0132, 2 }, ++ { 0xC8C0, 0xFFE8, 2 }, ++ { 0xC8C2, 0xFFDA, 2 }, ++ { 0xC8C4, 0xFECD, 2 }, ++ { 0xC8C6, 0x02C2, 2 }, ++ { 0xC8C8, 0x0075, 2 }, ++ { 0xC8CA, 0x011C, 2 }, ++ { 0xC8CC, 0x009A, 2 }, ++ { 0xC8CE, 0x0105, 2 }, ++ { 0xC8D0, 0x00A4, 2 }, ++ { 0xC8D2, 0x00AC, 2 }, ++ { 0xC8D4, 0x0A8C, 2 }, ++ { 0xC8D6, 0x0F0A, 2 }, ++ { 0xC8D8, 0x1964, 2 }, ++ ++ /* Automatic White balance */ ++ { MT9M114_CAM_AWB_AWB_XSHIFT_PRE_ADJ, 0x0033, 2 }, ++ { MT9M114_CAM_AWB_AWB_YSHIFT_PRE_ADJ, 0x003C, 2 }, ++ { MT9M114_CAM_AWB_AWB_XSCALE, 0x03, 1 }, ++ { MT9M114_CAM_AWB_AWB_YSCALE, 0x02, 1 }, ++ { 0xC8F4, 0x0000, 2 }, ++ { 0xC8F6, 0x0000, 2 }, ++ { 0xC8F8, 0x0000, 2 }, ++ { 0xC8FA, 0xE724, 2 }, ++ { 0xC8FC, 0x1583, 2 }, ++ { 0xC8FE, 0x2045, 2 }, ++ { 0xC900, 0x03FF, 2 }, ++ { 0xC902, 0x007C, 2 }, ++ { 0xC90C, 0x80, 1 }, ++ { 0xC90D, 0x80, 1 }, ++ { 0xC90E, 0x80, 1 }, ++ { 0xC90F, 0x88, 1 }, ++ { 0xC910, 0x80, 1 }, ++ { 0xC911, 0x80, 1 }, ++ ++ /* CPIPE Preference */ ++ { 0xC926, 0x0020, 2 }, ++ { 0xC928, 0x009A, 2 }, ++ { 0xC946, 0x0070, 2 }, ++ { 0xC948, 0x00F3, 2 }, ++ { 0xC944, 0x20, 1 }, ++ { 0xC945, 0x9A, 1 }, ++ { 0xC92A, 0x80, 1 }, ++ { 0xC92B, 0x4B, 1 }, ++ { 0xC92C, 0x00, 1 }, ++ { 0xC92D, 0xFF, 1 }, ++ { 0xC92E, 0x3C, 1 }, ++ { 0xC92F, 0x02, 1 }, ++ { 0xC930, 0x06, 1 }, ++ { 0xC931, 0x64, 1 }, ++ { 0xC932, 0x01, 1 }, ++ { 0xC933, 0x0C, 1 }, ++ { 0xC934, 0x3C, 1 }, ++ { 0xC935, 0x3C, 1 }, ++ { 0xC936, 0x3C, 1 }, ++ { 0xC937, 0x0F, 1 }, ++ { 0xC938, 0x64, 1 }, ++ { 0xC939, 0x64, 1 }, ++ { 0xC93A, 0x64, 1 }, ++ { 0xC93B, 0x32, 1 }, ++ { 0xC93C, 0x0020, 2 }, ++ { 0xC93E, 0x009A, 2 }, ++ { 0xC940, 0x00DC, 2 }, ++ { 0xC942, 0x38, 1 }, ++ { 0xC943, 0x30, 1 }, ++ { 0xC944, 0x50, 1 }, ++ { 0xC945, 0x19, 1 }, ++ { 0xC94A, 0x0230, 2 }, ++ { 0xC94C, 0x0010, 2 }, ++ { 0xC94E, 0x01CD, 2 }, ++ { 0xC950, 0x05, 1 }, ++ { 0xC951, 0x40, 1 }, ++ { 0xC87B, 0x1B, 1 }, ++ { MT9M114_CAM_AET_AEMODE, 0x0E, 1 }, ++ { 0xC890, 0x0080, 2 }, ++ { 0xC886, 0x0100, 2 }, ++ { 0xC87C, 0x005A, 2 }, ++ { 0xB42A, 0x05, 1 }, ++ { 0xA80A, 0x20, 1 }, ++ ++ { MT9M114_LOGICAL_ADDRESS_ACCESS, 0x0000, 2 }, ++ { MT9M114_CAM_PORT_OUTPUT_CONTROL, 0x8040, 2 }, ++ { MT9M114_PAD_SLEW, 0x0777, 2 }, ++}; ++ ++static const struct mt9m114_reg mt9m114_regs_qvga[] = { ++ { MT9M114_LOGICAL_ADDRESS_ACCESS, 0x1000, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_START, 0x0000, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_X_ADDR_START, 0x0000, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_END, 0x03CD, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_X_ADDR_END, 0x050D, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_ROW_SPEED, 0x0001, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN, 0x01C3, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 0x03F7, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES, 0x0500, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK, 0x04E2, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION, 0x00E0, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW, 0x01E3, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_REG_0_DATA, 0x0020, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_XOFFSET, 0x0000, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_YOFFSET, 0x0000, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_WIDTH, 0x0280, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_HEIGHT, 0x01E0, 2 }, ++ { MT9M114_CAM_CROP_CROPMODE, 0x03, 1 }, ++ { MT9M114_CAM_OUTPUT_WIDTH, 0x0140, 2 }, ++ { MT9M114_CAM_OUTPUT_HEIGHT, 0x00F0, 2 }, ++ { MT9M114_CAM_AET_AEMODE, 0x00, 1 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND, 0x013F, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND, 0x00EF, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND, 0x003F, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND, 0x002F, 2 }, ++}; ++ ++static const struct mt9m114_reg mt9m114_regs_vga[] = { ++ { MT9M114_LOGICAL_ADDRESS_ACCESS, 0x1000, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_START, 0x0000, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_X_ADDR_START, 0x0000, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_END, 0x03CD, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_X_ADDR_END, 0x050D, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_ROW_SPEED, 0x0001, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN, 0x01C3, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 0x03F7, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES, 0x0500, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK, 0x04E2, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION, 0x00E0, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW, 0x01E3, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_REG_0_DATA, 0x0020, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_XOFFSET, 0x0000, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_YOFFSET, 0x0000, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_WIDTH, 0x0280, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_HEIGHT, 0x01E0, 2 }, ++ { MT9M114_CAM_CROP_CROPMODE, 0x03, 1 }, ++ { MT9M114_CAM_OUTPUT_WIDTH, 0x0280, 2 }, ++ { MT9M114_CAM_OUTPUT_HEIGHT, 0x01E0, 2 }, ++ { MT9M114_CAM_AET_AEMODE, 0x00, 1 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND, 0x027F, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND, 0x01DF, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND, 0x007F, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND, 0x005F, 2 }, ++}; ++ ++static const struct mt9m114_reg mt9m114_regs_wvga[] = { ++ { MT9M114_LOGICAL_ADDRESS_ACCESS, 0x1000, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_START, 0x00F4, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_X_ADDR_START, 0x00F4, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_END, 0x02DB, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_X_ADDR_END, 0x041B, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_ROW_SPEED, 0x0001, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN, 0x00DB, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 0x045F, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES, 0x0500, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK, 0x04E2, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION, 0x0060, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW, 0x01E3, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_REG_0_DATA, 0x0020, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_XOFFSET, 0x0000, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_YOFFSET, 0x0000, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_WIDTH, 0x0320, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_HEIGHT, 0x01E0, 2 }, ++ { MT9M114_CAM_CROP_CROPMODE, 0x03, 1 }, ++ { MT9M114_CAM_OUTPUT_WIDTH, 0x0320, 2 }, ++ { MT9M114_CAM_OUTPUT_HEIGHT, 0x01E0, 2 }, ++ { MT9M114_CAM_AET_AEMODE, 0x00, 1 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND, 0x031F, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND, 0x01DF, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND, 0x009F, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND, 0x005F, 2 }, ++}; ++ ++static const struct mt9m114_reg mt9m114_regs_720p[] = { ++ { MT9M114_LOGICAL_ADDRESS_ACCESS, 0x1000, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_START, 0x0004, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_X_ADDR_START, 0x0004, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_END, 0x03CB, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_X_ADDR_END, 0x050B, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_ROW_SPEED, 0x0001, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN, 0x00DB, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 0x05B3, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES, 0x03EE, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK, 0x0636, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION, 0x0060, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW, 0x03C3, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_REG_0_DATA, 0x0020, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_XOFFSET, 0x0000, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_YOFFSET, 0x0000, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_WIDTH, 0x0500, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_HEIGHT, 0x03C0, 2 }, ++ { MT9M114_CAM_CROP_CROPMODE, 0x03, 1 }, ++ { MT9M114_CAM_OUTPUT_WIDTH, 0x0500, 2 }, ++ { MT9M114_CAM_OUTPUT_HEIGHT, 0x02D0, 2 }, ++ { MT9M114_CAM_AET_AEMODE, 0x00, 1 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_XEND, 0x04FF, 2 }, ++ { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND, 0x02CF, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART, 0x0000, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND, 0x00FF, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND, 0x008F, 2 }, ++}; ++ ++static const struct mt9m114_format { ++ enum v4l2_mbus_pixelcode mbus_code; ++ enum v4l2_colorspace colorspace; ++} mt9m114_formats[] = { ++ { ++ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, ++ .colorspace = V4L2_COLORSPACE_SRGB, ++ }, ++}; ++ ++static inline struct mt9m114 *to_mt9m114(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct mt9m114, sd); ++} ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct mt9m114, hdl)->sd; ++} ++ ++static int mt9m114_write8(struct i2c_client *client, u16 reg, u8 val) ++{ ++ int ret; ++ struct { ++ u16 reg; ++ u8 val; ++ } __packed buf; ++ struct i2c_msg msg = { ++ .addr = client->addr, ++ .flags = 0, ++ .len = 3, ++ .buf = (u8 *)&buf, ++ }; ++ buf.reg = swab16(reg); ++ buf.val = val; ++ ++ ret = i2c_transfer(client->adapter, &msg, 1); ++ if (ret < 0) { ++ v4l_err(client, "Failed to write register 0x%04x!\n", reg); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mt9m114_read16(struct i2c_client *client, u16 reg, u16 *val) ++{ ++ int ret; ++ u16 rval; ++ struct i2c_msg msg[] = { ++ { ++ .addr = client->addr, ++ .flags = 0, ++ .len = 2, ++ .buf = (u8 *)®, ++ }, ++ { ++ .addr = client->addr, ++ .flags = I2C_M_RD, ++ .len = 2, ++ .buf = (u8 *)&rval, ++ }, ++ }; ++ ++ reg = swab16(reg); ++ ++ ret = i2c_transfer(client->adapter, msg, 2); ++ if (ret < 0) { ++ v4l_err(client, "Failed to read register 0x%04x!\n", reg); ++ return ret; ++ } ++ *val = swab16(rval); ++ ++ return 0; ++} ++ ++static int mt9m114_write16(struct i2c_client *client, u16 reg, u16 val) ++{ ++ int ret; ++ struct { ++ u16 reg; ++ u16 val; ++ } __packed buf; ++ struct i2c_msg msg = { ++ .addr = client->addr, ++ .flags = 0, ++ .len = 4, ++ .buf = (u8 *)&buf, ++ }; ++ buf.reg = swab16(reg); ++ buf.val = swab16(val); ++ ++ ret = i2c_transfer(client->adapter, &msg, 1); ++ if (ret < 0) { ++ v4l_err(client, "Failed to write register 0x%04x!\n", reg); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mt9m114_write32(struct i2c_client *client, u16 reg, u32 val) ++{ ++ int ret; ++ struct { ++ u16 reg; ++ u32 val; ++ } __packed buf; ++ struct i2c_msg msg = { ++ .addr = client->addr, ++ .flags = 0, ++ .len = 6, ++ .buf = (u8 *)&buf, ++ }; ++ buf.reg = swab16(reg); ++ buf.val = swab32(val); ++ ++ ret = i2c_transfer(client->adapter, &msg, 1); ++ if (ret < 0) { ++ v4l_err(client, "Failed to write register 0x%04x!\n", reg); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mt9m114_writeregs(struct i2c_client *client, ++ const struct mt9m114_reg *regs, int len) ++{ ++ int i, ret; ++ ++ for (i = 0; i < len; i++) { ++ switch (regs[i].width) { ++ case 1: ++ ret = mt9m114_write8(client, ++ regs[i].reg, regs[i].val); ++ break; ++ case 2: ++ ret = mt9m114_write16(client, ++ regs[i].reg, regs[i].val); ++ break; ++ case 4: ++ ret = mt9m114_write32(client, ++ regs[i].reg, regs[i].val); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ if (ret < 0) ++ return ret; ++ } ++ return 0; ++} ++ ++static void mt9m114_res_roundup(u32 *width, u32 *height) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(mt9m114_resolutions); i++) ++ if ((mt9m114_resolutions[i].width >= *width) && ++ (mt9m114_resolutions[i].height >= *height)) { ++ *width = mt9m114_resolutions[i].width; ++ *height = mt9m114_resolutions[i].height; ++ return; ++ } ++ *width = mt9m114_resolutions[MT9M114_720P].width; ++ *height = mt9m114_resolutions[MT9M114_720P].height; ++} ++ ++static int mt9m114_set_res(struct i2c_client *client, u32 width, u32 height) ++{ ++ u16 read_mode; ++ ++ if ((width == mt9m114_resolutions[MT9M114_QVGA].width) ++ && (height == mt9m114_resolutions[MT9M114_QVGA].height)) { ++ mt9m114_writeregs(client, mt9m114_regs_qvga, ++ ARRAY_SIZE(mt9m114_regs_qvga)); ++ mt9m114_read16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, &read_mode); ++ read_mode = (read_mode & 0xfccf) | 0x0330; ++ mt9m114_write16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, read_mode); ++ } else if ((width == mt9m114_resolutions[MT9M114_VGA].width) ++ && (height == mt9m114_resolutions[MT9M114_VGA].height)) { ++ mt9m114_writeregs(client, mt9m114_regs_vga, ++ ARRAY_SIZE(mt9m114_regs_vga)); ++ mt9m114_read16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, &read_mode); ++ read_mode = (read_mode & 0xfccf) | 0x0330; ++ mt9m114_write16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, read_mode); ++ } else if ((width == mt9m114_resolutions[MT9M114_WVGA].width) ++ && (height == mt9m114_resolutions[MT9M114_WVGA].height)) { ++ mt9m114_writeregs(client, mt9m114_regs_wvga, ++ ARRAY_SIZE(mt9m114_regs_wvga)); ++ mt9m114_read16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, &read_mode); ++ read_mode &= 0xfccf; ++ mt9m114_write16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, read_mode); ++ } else if ((width == mt9m114_resolutions[MT9M114_720P].width) ++ && (height == mt9m114_resolutions[MT9M114_720P].height)) { ++ mt9m114_writeregs(client, mt9m114_regs_720p, ++ ARRAY_SIZE(mt9m114_regs_720p)); ++ mt9m114_read16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, &read_mode); ++ read_mode &= 0xfccf; ++ mt9m114_write16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, read_mode); ++ } else { ++ v4l_err(client, "Failed to select resolution!\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int mt9m114_set_state(struct i2c_client *client, u8 next_state) ++{ ++ int timeout = 100, ret; ++ u16 command; ++ ++ /* set the next desired state */ ++ ret = mt9m114_write8(client, MT9M114_SYSMGR_NEXT_STATE, next_state); ++ if (ret < 0) ++ return ret; ++ ++ /* start state transition */ ++ ret = mt9m114_write16(client, MT9M114_COMMAND_REGISTER, ++ (MT9M114_COMMAND_REGISTER_OK ++ | MT9M114_COMMAND_REGISTER_SET_STATE)); ++ if (ret < 0) ++ return ret; ++ ++ /* wait for the state transition to complete */ ++ while (timeout) { ++ ret = mt9m114_read16(client, ++ MT9M114_COMMAND_REGISTER, &command); ++ if (ret < 0) ++ return ret; ++ if (!(command & MT9M114_COMMAND_REGISTER_SET_STATE)) ++ break; ++ msleep(10); ++ timeout--; ++ } ++ if (!timeout) { ++ v4l_err(client, "Failed to poll command register\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* check if the command is successful */ ++ ret = mt9m114_read16(client, ++ MT9M114_COMMAND_REGISTER, &command); ++ if (ret < 0) ++ return ret; ++ if (command & MT9M114_COMMAND_REGISTER_OK) ++ return 0; ++ else ++ return -EFAULT; ++} ++ ++static int mt9m114_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_HFLIP: ++ { ++ u16 read_mode; ++ mt9m114_read16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, &read_mode); ++ read_mode = (read_mode & 0xfffe) | ctrl->val; ++ mt9m114_write16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, read_mode); ++ break; ++ } ++ case V4L2_CID_VFLIP: ++ { ++ u16 read_mode; ++ mt9m114_read16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, &read_mode); ++ read_mode = (read_mode & 0xfffd) | (ctrl->val << 1); ++ mt9m114_write16(client, ++ MT9M114_CAM_SENSOR_CONTROL_READ_MODE, read_mode); ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int mt9m114_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, ++ enum v4l2_mbus_pixelcode *code) ++{ ++ if (index >= ARRAY_SIZE(mt9m114_formats)) ++ return -EINVAL; ++ ++ *code = mt9m114_formats[index].mbus_code; ++ return 0; ++} ++ ++static int mt9m114_try_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ int index; ++ ++ for (index = 0; index < ARRAY_SIZE(mt9m114_formats); index++) ++ if (mt9m114_formats[index].mbus_code == fmt->code) ++ break; ++ if (index >= ARRAY_SIZE(mt9m114_formats)) { ++ /* default to first format */ ++ index = 0; ++ fmt->code = mt9m114_formats[0].mbus_code; ++ } ++ mt9m114_res_roundup(&fmt->width, &fmt->height); ++ ++ fmt->field = V4L2_FIELD_NONE; ++ fmt->colorspace = mt9m114_formats[index].colorspace; ++ return 0; ++} ++ ++static int mt9m114_s_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct mt9m114 *sensor = to_mt9m114(sd); ++ u16 output_fmt; ++ int ret; ++ ++ mt9m114_try_mbus_fmt(sd, fmt); ++ ++ /* set image size */ ++ ret = mt9m114_set_res(client, fmt->width, fmt->height); ++ if (ret < 0) ++ return ret; ++ ++ /* set image format */ ++ ret = mt9m114_read16(client, MT9M114_CAM_OUTPUT_FORMAT, &output_fmt); ++ if (ret < 0) ++ return ret; ++ output_fmt &= 0xc0fc; ++ switch (fmt->code) { ++ case V4L2_MBUS_FMT_UYVY8_2X8: ++ output_fmt |= 0x0002; ++ break; ++ case V4L2_MBUS_FMT_YUYV8_2X8: ++ break; ++ case V4L2_MBUS_FMT_RGB565_2X8_LE: ++ output_fmt |= 0x0102; ++ break; ++ case V4L2_MBUS_FMT_RGB565_2X8_BE: ++ output_fmt |= 0x0100; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ret = mt9m114_write16(client, MT9M114_CAM_OUTPUT_FORMAT, output_fmt); ++ if (ret < 0) ++ return ret; ++ ++ sensor->fmt = *fmt; ++ ++ return 0; ++} ++ ++static int mt9m114_g_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct mt9m114 *sensor = to_mt9m114(sd); ++ ++ *fmt = sensor->fmt; ++ return 0; ++} ++ ++static int mt9m114_g_parm(struct v4l2_subdev *sd, ++ struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ u16 frame_rate; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(*cp)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = 1; ++ mt9m114_read16(client, MT9M114_CAM_AET_MAX_FRAME_RATE, &frame_rate); ++ cp->timeperframe.denominator = frame_rate >> 8; ++ return 0; ++} ++ ++static int mt9m114_s_parm(struct v4l2_subdev *sd, ++ struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct v4l2_fract *tpf = &cp->timeperframe; ++ u16 frame_rate; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (tpf->numerator == 0 || tpf->denominator == 0 ++ || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) { ++ /* reset to max frame rate */ ++ tpf->numerator = 1; ++ tpf->denominator = MAX_FRAME_RATE; ++ } ++ frame_rate = (tpf->denominator / tpf->numerator) << 8; ++ mt9m114_write16(client, MT9M114_CAM_AET_MAX_FRAME_RATE, frame_rate); ++ mt9m114_write16(client, MT9M114_CAM_AET_MIN_FRAME_RATE, frame_rate); ++ return 0; ++} ++ ++static int mt9m114_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ ++ ret = mt9m114_set_state(client, ++ MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE); ++ if (ret < 0) ++ return ret; ++ if (enable) ++ ret = mt9m114_set_state(client, ++ MT9M114_SYS_STATE_START_STREAMING); ++ else ++ ret = mt9m114_set_state(client, ++ MT9M114_SYS_STATE_ENTER_SUSPEND); ++ return ret; ++} ++ ++static int mt9m114_g_chip_ident(struct v4l2_subdev *sd, ++ struct v4l2_dbg_chip_ident *chip) ++{ ++ u16 rev; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ mt9m114_read16(client, MT9M114_CUSTOMER_REV, &rev); ++ ++ return v4l2_chip_ident_i2c_client(client, chip, ++ V4L2_IDENT_MT9M114, rev); ++} ++ ++static const struct v4l2_ctrl_ops mt9m114_ctrl_ops = { ++ .s_ctrl = mt9m114_s_ctrl, ++}; ++ ++static const struct v4l2_subdev_core_ops mt9m114_core_ops = { ++ .g_chip_ident = mt9m114_g_chip_ident, ++}; ++ ++static const struct v4l2_subdev_video_ops mt9m114_video_ops = { ++ .enum_mbus_fmt = mt9m114_enum_mbus_fmt, ++ .try_mbus_fmt = mt9m114_try_mbus_fmt, ++ .s_mbus_fmt = mt9m114_s_mbus_fmt, ++ .g_mbus_fmt = mt9m114_g_mbus_fmt, ++ .s_parm = mt9m114_s_parm, ++ .g_parm = mt9m114_g_parm, ++ .s_stream = mt9m114_s_stream, ++}; ++ ++static const struct v4l2_subdev_ops mt9m114_ops = { ++ .core = &mt9m114_core_ops, ++ .video = &mt9m114_video_ops, ++}; ++ ++static int mt9m114_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct mt9m114 *sensor; ++ struct v4l2_subdev *sd; ++ struct v4l2_ctrl_handler *hdl; ++ u16 chip_id, command, output_control; ++ struct v4l2_mbus_framefmt default_fmt; ++ int ret; ++ ++ /* check if the adapter supports the needed features */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) ++ return -EIO; ++ ++ ret = mt9m114_read16(client, MT9M114_CHIP_ID, &chip_id); ++ if (ret < 0) { ++ v4l_err(client, "Failed to get chip id\n"); ++ return -ENODEV; ++ } ++ if (chip_id != 0x2481) { ++ v4l_err(client, "chip id 0x%04x mismatch\n", chip_id); ++ return -ENODEV; ++ } ++ ++ /* reset the sensor */ ++ ret = mt9m114_write16(client, MT9M114_SOFT_RESET, 0x0001); ++ if (ret < 0) { ++ v4l_err(client, "Failed to reset the sensor\n"); ++ return ret; ++ } ++ mt9m114_write16(client, MT9M114_SOFT_RESET, 0x0000); ++ mdelay(50); ++ ++ do { ++ ret = mt9m114_read16(client, ++ MT9M114_COMMAND_REGISTER, &command); ++ if (ret < 0) ++ return ret; ++ } while (command & MT9M114_COMMAND_REGISTER_SET_STATE); ++ ret = mt9m114_writeregs(client, mt9m114_init, ++ ARRAY_SIZE(mt9m114_init)); ++ if (ret < 0) { ++ v4l_err(client, "Failed to initialize the sensor\n"); ++ return ret; ++ } ++ ++ /* set the sensor in parallel data output mode */ ++ mt9m114_read16(client, MT9M114_CAM_PORT_OUTPUT_CONTROL, ++ &output_control); ++ output_control &= 0xfff8; ++ mt9m114_write16(client, MT9M114_CAM_PORT_OUTPUT_CONTROL, ++ output_control); ++ mt9m114_set_state(client, MT9M114_SYS_STATE_ENTER_CONFIG_CHANGE); ++ ++ sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); ++ if (sensor == NULL) ++ return -ENOMEM; ++ ++ sd = &sensor->sd; ++ v4l2_i2c_subdev_init(sd, client, &mt9m114_ops); ++ ++ default_fmt.width = mt9m114_resolutions[MT9M114_VGA].width; ++ default_fmt.height = mt9m114_resolutions[MT9M114_VGA].height; ++ default_fmt.code = V4L2_MBUS_FMT_YUYV8_2X8; ++ ret = mt9m114_s_mbus_fmt(sd, &default_fmt); ++ if (ret < 0) { ++ v4l_err(client, "Failed to set default format\n"); ++ kfree(sensor); ++ return -EFAULT; ++ } ++ ++ v4l_info(client, "chip found @ 0x%02x (%s)\n", ++ client->addr << 1, client->adapter->name); ++ ++ hdl = &sensor->hdl; ++ v4l2_ctrl_handler_init(hdl, 2); ++ v4l2_ctrl_new_std(hdl, &mt9m114_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(hdl, &mt9m114_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ /* hook the control handler into the driver */ ++ sd->ctrl_handler = hdl; ++ if (hdl->error) { ++ int err = hdl->error; ++ ++ v4l2_ctrl_handler_free(hdl); ++ kfree(sensor); ++ return err; ++ } ++ ++ /* initialize the hardware to the default control values */ ++ ret = v4l2_ctrl_handler_setup(hdl); ++ if (ret) { ++ v4l2_ctrl_handler_free(hdl); ++ kfree(sensor); ++ } ++ ++ return ret; ++} ++ ++static int mt9m114_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct mt9m114 *sensor = to_mt9m114(sd); ++ ++ v4l2_device_unregister_subdev(sd); ++ v4l2_ctrl_handler_free(sd->ctrl_handler); ++ kfree(sensor); ++ return 0; ++} ++ ++static const struct i2c_device_id mt9m114_id[] = { ++ {"mt9m114", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, mt9m114_id); ++ ++static struct i2c_driver mt9m114_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "mt9m114", ++ }, ++ .probe = mt9m114_probe, ++ .remove = mt9m114_remove, ++ .id_table = mt9m114_id, ++}; ++ ++module_i2c_driver(mt9m114_driver); ++ ++MODULE_DESCRIPTION("Aptina MT9M114 sensor driver"); ++MODULE_AUTHOR("Scott Jiang "); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c +index 9cee142..743b1cd 100644 +--- a/drivers/media/platform/soc_camera/cssp_camera.c ++++ b/drivers/media/platform/soc_camera/cssp_camera.c +@@ -1093,9 +1093,18 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + dev_dbg(&dev->pdev->dev, "width=%u height=%u byteperline=%u\n", + dev->width, dev->height, dev->bytesperline); + ++ /* Enable sensor clock before setting format */ ++ ret = clk_prepare_enable(dev->camera_clk); ++ if (ret != 0) { ++ dev_err(&dev->pdev->dev, "%s: clk_enable failed\n", ++ __func__); ++ return ret; ++ } ++ msleep(100); /* let the clock stabilize */ + /* Set the sensor into the new format */ + v4l2_fill_mbus_format(&mbus_fmt, pix, dev->fmt->code); + v4l2_subdev_call(dev->subdev, video, s_mbus_fmt, &mbus_fmt); ++ clk_disable_unprepare(dev->camera_clk); + + return 0; + } +@@ -1532,6 +1541,12 @@ of_get_cssp_platform_data(struct platform_device *pdev) + sizeof(pstore->i2c_camera.type)); + found = 1; + break; ++ } else if (of_device_is_compatible(npc, "aptina,mt9m114")) { ++ /* Add support for mt9m114 sensor VVDN */ ++ strncpy(pstore->i2c_camera.type, "mt9m114", ++ sizeof(pstore->i2c_camera.type)); ++ found = 1; ++ break; + } + } + +diff --git a/firmware/Makefile b/firmware/Makefile +index bff3bb1..67a0fcf 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -189,6 +189,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + BB-BONE-RST-00A0.dtbo \ + BB-BONE-RST2-00A0.dtbo \ + BB-BONE-CAM3-01-00A2.dtbo \ ++ BB-BONE-CAM-VVDN-00A0.dtbo \ + TT3201-001-01.dtbo \ + BB-BONE-SERL-03-00A1.dtbo \ + BB-BONE-BACON-00A0.dtbo \ +diff --git a/firmware/capes/BB-BONE-CAM-VVDN-00A0.dts b/firmware/capes/BB-BONE-CAM-VVDN-00A0.dts +new file mode 100644 +index 0000000..b64c7f2 +--- /dev/null ++++ b/firmware/capes/BB-BONE-CAM-VVDN-00A0.dts +@@ -0,0 +1,230 @@ ++/* ++ * Copyright (C) 2013 VVDN Technologies ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-APTU-CAM"; ++ version = "00A0", "A0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header uses */ ++ "P8.25", /* gpmc: gpmc_ad0 */ ++ "P8.24", /* gpmc: gpmc_ad1 */ ++ "P8.5", /* gpmc: gpmc_ad2 */ ++ "P8.6", /* gpmc: gpmc_ad3 */ ++ "P8.23", /* gpmc: gpmc_ad4 */ ++ "P8.22", /* gpmc: gpmc_ad5 */ ++ "P8.3", /* gpmc: gpmc_ad6 */ ++ "P8.4", /* gpmc: gpmc_ad7 */ ++ "P8.19", /* gpmc: gpmc_ad8 */ ++ "P8.13", /* gpmc: gpmc_ad9 */ ++ "P8.14", /* gpmc: gpmc_ad10 */ ++ "P8.17", /* gpmc: gpmc_ad11 */ ++ "P8.12", /* gpmc: gpmc_ad12 */ ++ "P8.11", /* gpmc: gpmc_ad13 */ ++ "P8.16", /* gpmc: gpmc_ad14 */ ++ "P8.15", /* gpmc: gpmc_ad15 */ ++ "P9.13", /* gpmc: gpmc_wpn */ ++ "P8.21", /* gpmc: gpmc_csn1 */ ++ "P8.18", /* gpmc: gpmc_clk */ ++ "P8.7", /* gpmc: gpmc_advn_ale */ ++ "P8.8", /* gpmc: gpmc_oen_ren */ ++ "P8.10", /* gpmc: gpmc_wen */ ++ "P8.9", /* gpmc: gpmc_ben0_cle */ ++ "P9.41", /* cssp: clkout2 */ ++ "P9.42", /* cssp: xdma_event_intr2 */ ++ "P9.18", /* cssp: gpio0_4 */ ++ "P9.17", /* cssp: gpio0_5 */ ++ "P9.11", /* cssp: gpio0_30 */ ++ ++ /* the hardware IP uses */ ++ "gpio0_4", ++ "gpio0_5", ++ "gpio0_30", ++ "gpmc", ++ "clkout2", ++ /* the reset pin */ ++ "eMMC_RSTn"; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ gpmc_pins: pinmux_gpmc_pins { ++ pinctrl-single,pins = < ++ 0x000 0x30 /* gpmc_ad0.gpmc_ad0 MODE0 | INPUT | PULLUP */ ++ 0x004 0x30 /* gpmc_ad1.gpmc_ad1 MODE0 | INPUT | PULLUP */ ++ 0x008 0x30 /* gpmc_ad2.gpmc_ad2 MODE0 | INPUT | PULLUP */ ++ 0x00C 0x30 /* gpmc_ad3.gpmc_ad3 MODE0 | INPUT | PULLUP */ ++ 0x010 0x30 /* gpmc_ad4.gpmc_ad4 MODE0 | INPUT | PULLUP */ ++ 0x014 0x30 /* gpmc_ad5.gpmc_ad5 MODE0 | INPUT | PULLUP */ ++ 0x018 0x30 /* gpmc_ad6.gpmc_ad6 MODE0 | INPUT | PULLUP */ ++ 0x01C 0x30 /* gpmc_ad7.gpmc_ad7 MODE0 | INPUT | PULLUP */ ++ 0x020 0x30 /* gpmc_ad8.gpmc_ad8 MODE0 | INPUT | PULLUP */ ++ 0x024 0x30 /* gpmc_ad9.gpmc_ad9 MODE0 | INPUT | PULLUP */ ++ 0x028 0x30 /* gpmc_ad10.gpmc_ad10 MODE0 | INPUT | PULLUP */ ++ 0x02C 0x30 /* gpmc_ad11.gpmc_ad11 MODE0 | INPUT | PULLUP */ ++ 0x030 0x30 /* gpmc_ad12.gpmc_ad12 MODE0 | INPUT | PULLUP */ ++ 0x034 0x30 /* gpmc_ad13.gpmc_ad13 MODE0 | INPUT | PULLUP */ ++ 0x038 0x30 /* gpmc_ad14.gpmc_ad14 MODE0 | INPUT | PULLUP */ ++ 0x03C 0x30 /* gpmc_ad15.gpmc_ad15 MODE0 | INPUT | PULLUP */ ++ 0x074 0x30 /* gpmc_wpn.gpmc_wpn MODE0 | INPUT | PULLUP */ /* WAS MODE 7 */ ++ 0x080 0x08 /* gpmc_cscn1.gpmc_cscn1 MODE0 | OUTPUT */ ++ 0x08C 0x28 /* gpmc_clk.gpmc_clk MODE0 | INPUT */ ++ 0x090 0x08 /* gpmc_advn_ale.gpmc_advn_ale MODE0 | OUTPUT */ ++ 0x094 0x08 /* gpmc_oen_ren.gpmc_oen_ren MODE0 | OUTPUT */ ++ 0x098 0x08 /* gpmc_wen.gpmc_wen MODE0 | OUTPUT */ ++ 0x09C 0x08 /* gpmc_ben0_cle.gpmc_ben0_cle MODE0 | OUTPUT */ ++ >; ++ }; ++ cssp_camera_pins: pinmux_cssp_camera_pins { ++ pinctrl-single,pins = < ++ /* clkout2 */ ++ 0x1B4 0x03 /* xdma_event_intr1.clkout2 MODE3 | OUTPUT clkout2 */ ++ ++ /* dmar */ ++ 0x164 0x2e /* ecap0_in_pwm0_out.xdma_event_intr2 MODE6 | INPUT */ ++ ++ /* cssp camera */ ++ 0x158 0x07 /* spi0_d1.gpio0_4 MODE7 | OUTPUT, QL CSSP and Camera Sensor Reset */ ++ 0x15C 0x17 /* spi0_cs0.gpio0_5 MODE7 | OUTPUT | PULLUP, 1V8 and 2V8 Power Enable */ ++ 0x070 0x2f /* gpmc_wait0.gpio0_30 MODE0 | INPUT | PULLUPDIS, Sensor orientation detect: low -> frontfacing, high -> backfacing */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpmc>; ++ depth = <1>; /* only create devices on depth 1 */ ++ ++ /* stupid warnings */ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ __overlay__ { ++ ++ status = "okay"; ++ ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gpmc_pins>; ++ ++ /* chip select ranges */ ++ ranges = <0 0 0x08000000 0x10000000>, /* bootloader has this enabled */ ++ <1 0 0x18000000 0x08000000>, ++ <2 0 0x20000000 0x08000000>, ++ <3 0 0x28000000 0x08000000>, ++ <4 0 0x30000000 0x08000000>, ++ <5 0 0x38000000 0x04000000>, ++ <6 0 0x3c000000 0x04000000>; ++ ++ /* ++ * This is complete and utter cr*p ++ * It doesn't belong here, but we don't ++ * have a memory controller abstraction. ++ * So we muddle along... ++ */ ++ camera { ++ compatible = "cssp-camera"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cssp_camera_pins>; ++ ++ reg = <1 0 0x01000000>; /* CS1 */ ++ ++ bank-width = <2>; /* GPMC_CONFIG1_DEVICESIZE(1) */ ++ ++ gpmc,burst-read; /* GPMC_CONFIG1_READMULTIPLE_SUPP */ ++ gpmc,sync-read; /* GPMC_CONFIG1_READTYPE_SYNC */ ++ gpmc,sync-write; /* GPMC_CONFIG1_WRITETYPE_SYNC */ ++ gpmc,clk-activation-ns = <20>; /* GPMC_CONFIG1_CLKACTIVATIONTIME(2) */ ++ gpmc,burst-length = <16>; /* GPMC_CONFIG1_PAGE_LEN(2) */ ++ gpmc,mux-add-data = <2>; /* GPMC_CONFIG1_MUXTYPE(2) */ ++ ++ gpmc,sync-clk-ps = <20000>; /* CONFIG2 */ ++ ++ gpmc,cs-on-ns = <1>; ++ gpmc,cs-rd-off-ns = <160>; ++ gpmc,cs-wr-off-ns = <310>; ++ ++ gpmc,adv-on-ns = <0>; /* CONFIG3 */ ++ gpmc,adv-rd-off-ns = <40>; ++ gpmc,adv-wr-off-ns = <40>; ++ ++ gpmc,we-on-ns = <60>; /* CONFIG4 */ ++ gpmc,we-off-ns = <310>; ++ gpmc,oe-on-ns = <60>; ++ gpmc,oe-off-ns = <160>; ++ ++ gpmc,page-burst-access-ns = <20>; /* CONFIG 5 */ ++ gpmc,access-ns = <140>; ++ gpmc,rd-cycle-ns = <160>; ++ gpmc,wr-cycle-ns = <310>; ++ ++ gpmc,wr-access-ns = <100>; /* CONFIG 6 */ ++ gpmc,wr-data-mux-bus-ns = <60>; ++ ++ gpmc,bus-turnaround-ns = <40>; /* CONFIG6:3:0 = 4 */ ++ gpmc,cycle2cycle-samecsen; /* CONFIG6:7 = 1 */ ++ gpmc,cycle2cycle-delay-ns = <40>; /* CONFIG6:11:8 = 4 */ ++ ++ /* not using dma engine yet, but we can get the channel number here */ ++ dmas = <&edma 20>; ++ dma-names = "cssp"; ++ ++ /* clocks */ ++ cssp,camera-clk-name = "adjustable_clkout2_ck"; ++ cssp,camera-clk-rate = <32000000>; ++ ++ /* reset */ ++ reset-gpio = <&gpio1 4 0>; ++ ++ /* orientation; -> MT9T112_FLAG_VFLIP */ ++ orientation-gpio = <&gpio1 30 0>; ++ ++ /* reset controller (for the black) */ ++ reset = <&rstctl 0 0>; ++ reset-names = "eMMC_RSTn-CAM3"; ++ ++ /* camera sensor */ ++ cssp,sensor { ++ i2c-adapter = <&i2c2>; ++ ++ /* need it to stop the whinning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* i2c device node */ ++ m59t112 { ++ compatible = "aptina,mt9m114"; ++ reg = <0x48>; ++ ++ /* dummy pll flags m, n, p1-7, PLL hardcoded in Driver */ ++ flags = <0>; ++ pll-divider = <0 0 0 0 0 0 0 0 0>; ++ }; ++ }; ++ ++ }; ++ ++ }; ++ }; ++ ++}; +diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h +index 4ee125b..210737b 100644 +--- a/include/media/v4l2-chip-ident.h ++++ b/include/media/v4l2-chip-ident.h +@@ -304,6 +304,7 @@ enum { + V4L2_IDENT_MT9M001C12STM = 45005, + V4L2_IDENT_MT9M111 = 45007, + V4L2_IDENT_MT9M112 = 45008, ++ V4L2_IDENT_MT9M114 = 45009, + V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ + V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ + V4L2_IDENT_MT9T031 = 45020, +-- +1.8.4.3 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0020-add-argus-ups-cape-support.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0020-add-argus-ups-cape-support.patch new file mode 100644 index 00000000..53aaa565 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0020-add-argus-ups-cape-support.patch @@ -0,0 +1,577 @@ +From fd541de6bde6f13d3792433ac89033e4b018aed0 Mon Sep 17 00:00:00 2001 +From: Dave Lambert +Date: Thu, 12 Dec 2013 12:02:16 -0600 +Subject: [PATCH 20/20] add argus ups cape support + +Signed-off-by: Dave Lambert +Signed-off-by: Robert Nelson +--- + drivers/misc/cape/beaglebone/Kconfig | 7 + + drivers/misc/cape/beaglebone/Makefile | 1 + + drivers/misc/cape/beaglebone/cape-bone-argus.c | 412 +++++++++++++++++++++++++ + firmware/Makefile | 4 + + firmware/capes/cape-bone-argus-00A0.dts | 90 ++++++ + 5 files changed, 514 insertions(+) + create mode 100644 drivers/misc/cape/beaglebone/cape-bone-argus.c + create mode 100644 firmware/capes/cape-bone-argus-00A0.dts + +diff --git a/drivers/misc/cape/beaglebone/Kconfig b/drivers/misc/cape/beaglebone/Kconfig +index 0f44f7a..ae58216 100644 +--- a/drivers/misc/cape/beaglebone/Kconfig ++++ b/drivers/misc/cape/beaglebone/Kconfig +@@ -31,6 +31,13 @@ config CAPE_BEAGLEBONE_GEIGER + help + Say Y here to include support for the Geiger Cape + ++config CAPE_BEAGLEBONE_ARGUS ++ tristate "Beaglebone Argus UPS Cape" ++ depends on CAPE_BEAGLEBONE ++ default n ++ help ++ Say Y here to include support for the Argus UPS cape ++ + + config CAPE_BEAGLEBONE_NIXIE + tristate "Beaglebone Nixie Cape" +diff --git a/drivers/misc/cape/beaglebone/Makefile b/drivers/misc/cape/beaglebone/Makefile +index e32550d..097e25b 100644 +--- a/drivers/misc/cape/beaglebone/Makefile ++++ b/drivers/misc/cape/beaglebone/Makefile +@@ -7,4 +7,5 @@ obj-$(CONFIG_BEAGLEBONE_IIO_HELPER) += bone-iio-helper.o + + obj-$(CONFIG_CAPE_BEAGLEBONE) += capemgr.o + obj-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += cape-bone-geiger.o ++obj-$(CONFIG_CAPE_BEAGLEBONE_ARGUS) += cape-bone-argus.o + obj-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += cape-bone-nixie.o +diff --git a/drivers/misc/cape/beaglebone/cape-bone-argus.c b/drivers/misc/cape/beaglebone/cape-bone-argus.c +new file mode 100644 +index 0000000..b92f561 +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/cape-bone-argus.c +@@ -0,0 +1,412 @@ ++/* -*- linux-c -*- */ ++ ++/* Linux Kernel Module for Breakaway Systems UPS control. ++ * ++ * PUBLIC DOMAIN ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Module to sync file systems leaving them mounted read-only, ++ * then signal the UPS that it is safe to remove ++ * power, and finally halt the processor. ++ * Also to allow kicking the watchdog from user mode. ++ */ ++ ++#define N_GPIOS 9 /* Total number of GPIOS used */ ++ ++#define REQ_GPIO_IDX 0 /* Indices got GPIOS */ ++#define ACK_GPIO_IDX 1 ++#define WDG_GPIO_IDX 2 ++#define LED1_GREEN_IDX 3 ++#define LED1_RED_IDX 4 ++#define LED2_GREEN_IDX 5 ++#define LED2_RED_IDX 6 ++#define GEN_OUT1_IDX 7 ++#define GEN_OUT2_IDX 8 ++ ++static struct argus_ups_info { /* As there is only one UPS device we can make this static */ ++ struct fasync_struct *async_queue; /* asynchronous readers */ ++ struct platform_device *pdev; ++ struct pwm_device *pwm_dev; ++ struct gpio gpios[N_GPIOS]; ++} info = {NULL, NULL, NULL, /* Some fields filled in by device tree, probe, etc. */ ++ { ++ {-1, GPIOF_IN, "Powerdown request"}, ++ {-1, GPIOF_OUT_INIT_LOW, "Powerdown acknowledge" }, ++ {-1, GPIOF_OUT_INIT_LOW, "Watchdog"}, ++ {-1, GPIOF_OUT_INIT_LOW, "LED 1 Green"}, ++ {-1, GPIOF_OUT_INIT_LOW, "LED 1 Red"}, ++ {-1, GPIOF_OUT_INIT_LOW, "LED 2 Green"}, ++ {-1, GPIOF_OUT_INIT_LOW, "LED 2 Red"}, ++ {-1, GPIOF_OUT_INIT_LOW, "General Output #1"}, ++ {-1, GPIOF_OUT_INIT_LOW, "General Output #2"} ++ }, ++}; ++ ++ ++static const struct of_device_id argus_ups_of_ids[] = { ++ { .compatible = "argus-ups" }, ++ { } ++}; ++ ++static int argus_ups_major; /* Major device number */ ++ ++static struct class *argus_ups_class; /* /sys/class */ ++ ++dev_t argus_ups_dev; /* Device number */ ++ ++static struct cdev *argus_ups_cdev; /* Character device details */ ++ ++static void argus_ups_function(struct work_struct *ignored); /* Work function */ ++ ++static DECLARE_DELAYED_WORK(argus_ups_work, argus_ups_function); /* Kernel workqueue glue */ ++ ++static struct workqueue_struct *argus_ups_workqueue; /* Kernel workqueue */ ++ ++static int debug = 0; ++module_param(debug, int, S_IRUGO); ++MODULE_PARM_DESC(debug, "Debug flag"); ++ ++static int shutdown = 1; ++module_param(shutdown, int, S_IRUGO); ++MODULE_PARM_DESC(shutdown, "Shutdown flag"); ++ ++static char* fs_type_names[] = {"vfat", "ext4"}; /* File system names that may need syncing. */ ++ ++/* Just kick watchdog */ ++ ++static ssize_t argus_ups_write(struct file *filp, const char __user *buf, size_t count, ++ loff_t *f_pos) ++{ ++ int i; ++ if (debug >= 3) { ++ printk("Writing to watchdog - count:%d\n", count); ++ } ++ for (i = 0; i < count; i++) { ++ gpio_set_value(info.gpios[WDG_GPIO_IDX].gpio, 1); /* Set it */ ++ msleep(10); /* Wait */ ++ gpio_set_value(info.gpios[WDG_GPIO_IDX].gpio, 0); /* End clearing it */ ++ msleep(10); ++ } ++ return count; /* Always returns what we sent, regardsless */ ++} ++ ++static long argus_ups_ioctl(struct file *file, ++ unsigned int ioctl, ++ unsigned long param) ++{ ++ if (debug >= 4) { ++ printk(KERN_ERR "ioctl: %d, param: %ld\n", ioctl, param); ++ } ++ switch(ioctl) { ++ case 10001: { ++ debug = param; ++ printk("Debug set to %d\n", debug); ++ break; ++ } ++ case 10002: { ++ unsigned char value = param & 0x0F; ++ unsigned char mask = (param >> 4) & 0x0F; ++ int i; /* Loop iterator */ ++ if (mask == 0) { ++ printk(KERN_ERR "Pointless mask of zero!\n"); ++ } ++ for (i = 0; i < 4; i++) { /* For all four LEDS */ ++ if (mask & (1 << i)) { /* Only masked values */ ++ if (value & (1 << i)) { /* On - so gpio is hi */ ++ if (debug >= 4) { ++ printk("Setting %d hi, ", ++ info.gpios[LED1_GREEN_IDX + i].gpio); ++ } ++ gpio_set_value(info.gpios[LED1_GREEN_IDX + i].gpio, 1); ++ } ++ else { /* Off - so gpio is lo */ ++ if (debug >= 4) { ++ printk("Setting %d lo, ", ++ info.gpios[LED1_GREEN_IDX + i].gpio); ++ } ++ gpio_set_value(info.gpios[LED1_GREEN_IDX + i].gpio, 0); ++ } ++ } ++ } ++ if (debug >= 4) { ++ printk("\n"); ++ } ++ break; ++ } ++ case 10003: { ++ gpio_set_value(info.gpios[GEN_OUT1_IDX].gpio, param & 1); ++ break; ++ } ++ case 10004: { ++ gpio_set_value(info.gpios[GEN_OUT2_IDX].gpio, param & 1); ++ break; ++ } ++ default: ++ { ++ printk(KERN_ERR "Invalid ioctl %d\n", ioctl); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static int argus_ups_fasync(int fd, struct file *filp, int mode) ++{ ++ printk(KERN_ERR "In argus_ups_fasync() fd:%d, filp:%p, mode:%d\n", fd, filp, mode); ++ return fasync_helper(fd, filp, mode, &info.async_queue); ++} ++ ++static struct file_operations argus_ups_fops = { /* Only file operation is to kick watchdog via a write */ ++ .owner = THIS_MODULE, ++ .llseek = NULL, ++ .read = NULL, ++ .unlocked_ioctl = argus_ups_ioctl, ++ .write = argus_ups_write, ++ .open = NULL, ++ .release = NULL, ++ .fasync = argus_ups_fasync, ++}; ++ ++ ++static void remount_sb(struct super_block *sb) ++{ ++ int flags = MS_RDONLY; ++ int result = sb->s_op->remount_fs(sb, &flags, ""); ++ if (debug) { ++ printk("Processing superblock %p\n", sb); ++ printk("Remount operation returned %d\n", result); ++ } ++} ++ ++ ++static void argus_ups_function(struct work_struct *ignored) ++{ ++ static int testdata = 0; /* Data for test */ ++ int i; /* Iterator */ ++ testdata++; ++ if (!gpio_get_value(info.gpios[REQ_GPIO_IDX].gpio)) { ++ queue_delayed_work(argus_ups_workqueue, &argus_ups_work, HZ/100); /* Re-queue in 10mS*/ ++ return; ++ } ++ printk(KERN_ERR "Request received\n"); ++ if (debug) { ++ printk("Shutdown request received from UPS\n"); ++ } ++ if (!shutdown) { ++ printk("Shutdown request ignored\n"); ++ return; ++ } ++ ++ if (debug) { ++ printk("Sending async kill SIGIO to %p\n", info.async_queue); ++ } ++ if (info.async_queue) { /* Try and tell usermode to halt system */ ++ kill_fasync(&info.async_queue, SIGIO, POLL_IN); ++ } ++ gpio_set_value(info.gpios[LED1_GREEN_IDX].gpio, 0); /* Turn off green LED1 */ ++ for (i = 0; i < 300; i++) { /* Toggle acknowledge at 10 Hz for 15 seconds */ ++ if (debug >= 2) { ++ printk("Waiting for first shutdown request:%d\n", i); ++ } ++ gpio_set_value(info.gpios[ACK_GPIO_IDX].gpio, i & 1); /* Toggle acknowledge */ ++ gpio_set_value(info.gpios[LED1_RED_IDX].gpio, i & 1); /* and LED1 red */ ++ msleep(50); /* Wait in 50ms increments */ ++ } ++ ++ { ++ char *argv[] = { "/sbin/halt", NULL }; ++ static char *envp[] = { ++ "HOME=/", ++ "TERM=linux", ++ "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin", NULL }; ++ ++ call_usermodehelper( argv[0], argv, envp, UMH_WAIT_PROC ); ++ } ++ for (i = 0; i < 300; i++) { /* Toggle acknowledge at 10 Hz for 15 more seconds */ ++ if (debug >= 2) { ++ printk("Waiting for second shutdown request:%d\n", i); ++ } ++ gpio_set_value(info.gpios[ACK_GPIO_IDX].gpio, i & 1); /* Toggle acknowledge */ ++ gpio_set_value(info.gpios[LED1_RED_IDX].gpio, i & 1); /* and LED1 red */ ++ msleep(50); /* Wait in 50ms increments */ ++ } ++ printk(KERN_ERR "Usermode failed to halt system\n"); ++ kernel_halt(); /* Last resort - may give some oopss */ ++} ++ ++ ++static int argus_ups_probe(struct platform_device *pdev) /* Entry point */ ++{ ++ struct pinctrl *pinctrl; ++ struct device_node *pnode = pdev->dev.of_node; ++ int i; ++ int ret; ++ printk("Init UPS module - debug=%d, shutdown=%d\n", ++ debug, shutdown); ++ platform_set_drvdata(pdev, &info); ++ info.pdev = pdev; ++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev); ++ if (IS_ERR(pinctrl)) { ++ dev_warn(&pdev->dev, ++ "pins are not configured from the driver\n"); ++ return -1; ++ } ++ ret = of_property_read_u32(pnode, "debug", &debug); ++ if (ret != 0) { ++ dev_err(&pdev->dev, "Unable to read debug parameter\n"); ++ } ++ else { ++ printk("Debug parameter read from DT:%d\n", debug); ++ } ++ ++ ret = of_property_read_u32(pnode, "shutdown", &shutdown); ++ if (ret != 0) { ++ dev_err(&pdev->dev, "Unable to read shutdown parameter\n"); ++ } ++ else { ++ printk("Shutdown parameter read from DT:%d\n", shutdown); ++ } ++ ++ ret = of_gpio_count(pnode); ++ ++ if (ret != N_GPIOS) { ++ printk(KERN_ERR "Wrong number of gpios"); ++ return -1; ++ } ++ ++ for (i = 0; i < of_gpio_count(pnode); i++) { ++ ret = of_get_gpio_flags(pnode, i, NULL); ++ if (debug) { ++ printk("GPIO#%d:%d\n", i, ret); ++ } ++ if (IS_ERR_VALUE(ret)) { ++ dev_err(&pdev->dev, "unable to get GPIO %d\n", i); ++ goto err_no_gpio; ++ } ++ info.gpios[i].gpio = ret; ++ } ++ ++ ++ ret = alloc_chrdev_region(&argus_ups_dev, 0, 2, "argus_ups"); ++ argus_ups_major = MAJOR(argus_ups_dev); ++ if (ret) { ++ printk(KERN_ERR "Error %d adding argus_ups\n", ret); ++ return -1; ++ } ++ if (debug) { ++ printk("argus_ups major: %d\n", argus_ups_major); ++ } ++ argus_ups_cdev = cdev_alloc(); /* Make this a character device */ ++ argus_ups_cdev->ops = &argus_ups_fops; /* File operations */ ++ argus_ups_cdev->owner = THIS_MODULE; /* Top level device */ ++ ret = cdev_add(argus_ups_cdev, argus_ups_dev, 1); /* Add it to the kernel */ ++ if (ret) { ++ printk(KERN_ERR "cdev_add returned %d\n", ret); ++ unregister_chrdev_region(0, 1); ++ return -1; ++ } ++ ret = gpio_request_array(info.gpios, N_GPIOS); ++ if (ret) { ++ printk(KERN_ERR "Error %d requesting GPIOs\n", ret); ++ unregister_chrdev_region(0, 1); ++ return -1; ++ } ++ ++ argus_ups_class = class_create(THIS_MODULE, "argus_ups"); /* /sys/class entry for udev */ ++ if (IS_ERR(argus_ups_class)) { ++ printk(KERN_ERR "Error creating argus_ups_class\n"); ++ unregister_chrdev_region(0, 1); ++ return -1; ++ } ++ device_create(argus_ups_class, NULL, MKDEV(argus_ups_major, 0), NULL, "argus_ups"); ++ argus_ups_workqueue = create_singlethread_workqueue("argus_ups"); ++ INIT_DELAYED_WORK(&argus_ups_work, argus_ups_function); ++ queue_delayed_work(argus_ups_workqueue, &argus_ups_work, 0); /* Start work immediately */ ++ ++ return 0; ++err_no_gpio: ++ return ret; ++ ++} ++ ++ ++static void argus_ups_cleanup(void) ++{ ++ printk("Module cleanup called\n"); ++ while (cancel_delayed_work(&argus_ups_work) == 0) { ++ flush_workqueue(argus_ups_workqueue); /* Make sure all work is completed */ ++ } ++ destroy_workqueue(argus_ups_workqueue); ++ gpio_free_array(info.gpios, N_GPIOS); ++ device_destroy(argus_ups_class, argus_ups_dev); ++ class_destroy(argus_ups_class); ++ unregister_chrdev_region(argus_ups_dev, 1); ++ cdev_del(argus_ups_cdev); ++} ++ ++ ++ ++static int argus_ups_remove(struct platform_device *pdev) ++{ ++ printk("In argus_ups_remove()\n"); ++ argus_ups_cleanup(); ++ printk("After cleanup\n"); ++ return 0; ++} ++ ++#define ARGUS_UPS_PM_OPS NULL ++ ++struct platform_driver argus_ups_driver = { ++ .probe = argus_ups_probe, ++ .remove = argus_ups_remove, ++ .driver = { ++ .name = "argus-ups", ++ .owner = THIS_MODULE, ++ .pm = ARGUS_UPS_PM_OPS, ++ .of_match_table = argus_ups_of_ids, ++ }, ++}; ++ ++ ++static int __init argus_ups_init(void) ++{ ++ return platform_driver_probe(&argus_ups_driver, ++ argus_ups_probe); ++} ++ ++static void __exit argus_ups_exit(void) ++{ ++ platform_driver_unregister(&argus_ups_driver); ++ printk("After driver unregister\n"); ++} ++ ++module_init(argus_ups_init); ++module_exit(argus_ups_exit); ++ ++/* ++ * Get rid of taint message. ++ */ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("David Lambert"); /* Who wrote this module? */ ++MODULE_DESCRIPTION("Argus UPS control"); /* What does this module do */ ++MODULE_ALIAS("platform:argus-ups"); ++MODULE_DEVICE_TABLE(of, argus_ups_of_ids); +diff --git a/firmware/Makefile b/firmware/Makefile +index 67a0fcf..e45d10b 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -203,6 +203,10 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \ + cape-bone-geiger-00A0.dtbo + ++# the Argus UPS cape ++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_ARGUS) += \ ++ cape-bone-argus-00A0.dtbo ++ + # the nixie cape + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += \ + cape-bone-nixie-00A0.dtbo +diff --git a/firmware/capes/cape-bone-argus-00A0.dts b/firmware/capes/cape-bone-argus-00A0.dts +new file mode 100644 +index 0000000..26ce46e +--- /dev/null ++++ b/firmware/capes/cape-bone-argus-00A0.dts +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (C) 2013 David Lambert - Breakaway Systems LLC> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This has been, and continues to be very confusing to me!!! ++ * ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "argus-ups"; ++ version = "00A0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header usage */ ++ "P8.11", /* Request from UPS */ ++ "P8.17", /* Acknowledge to UPS */ ++ "P8.18", /* Watchdog to UPS */ ++ "P8.7", /* LED 1 Green */ ++ "P8.8", /* LED 1 Red */ ++ "P8.9", /* LED 2 Green */ ++ "P8.10", /* LED 2 Red */ ++ "P9.41", /* General Output #1 */ ++ "P9.42", /* General Output #2 */ ++ /* the hardware IP usage - note that gpios here need to be numbered 0-n */ ++ /* whereas in the fragments they are numbered 1-(n+1)????? */ ++ "gpio0_30", ++ "gpio0_5", ++ "gpio0_4", ++ "gpio2_2", /* LED 1 Green */ ++ "gpio2_3", /* LED 1 Red */ ++ "gpio2_5", /* LED 2 Green */ ++ "gpio2_4", /* LED 2 Red */ ++ "gpio0_20", /* General Output #1 */ ++ "gpio0_7"; /* General Output #2 */ ++ ++ fragment@0 { /* Deals with the pinmux */ ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ argus_ups_pins: pinmux_argus_ups_pins { /* Set up pinmux */ ++ pinctrl-single,pins = < ++ 0x070 0x27 /* gpmc_wait0.gpio0_30, OMAP_MUX_MODE7 | INPUT_PULLDOWN */ ++ 0x15c 0x17 /* spi0_cs0.gpio0_5, OMAP_MUX_MODE7 | OUTPUT_PULLUP */ ++ 0x158 0x17 /* spi0_d1.gpio0_4, OMAP_MUX_MODE7 | OUTPUT_PULLUP */ ++ 0x090 0x17 /* gpmc_advn_ale.gpio_2 , OMAP_MUX_MODE7 | OUTPUT_PULLUP */ ++ 0x094 0x17 /* gpmc_oen_ren.gpio2_3 , OMAP_MUX_MODE7 | OUTPUT_PULLUP */ ++ 0x09c 0x17 /* gpmc_ben0_cle.gpio2_5 , OMAP_MUX_MODE7 | OUTPUT_PULLUP */ ++ 0x098 0x17 /* gpmc_gpmc_wen.gpio2_4 , OMAP_MUX_MODE7 | OUTPUT_PULLUP */ ++ 0x1b4 0x17 /* xdma_event_intr1.gpio0_20 , OMAP_MUX_MODE7 | OUTPUT_PULLUP */ ++ 0x164 0x17 /* ecap0_in_pwm0_out.gpio0_7 , OMAP_MUX_MODE7 | OUTPUT_PULLUP */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&ocp>; ++ __overlay__ { ++ argus-ups { ++ compatible = "argus-ups"; ++ status = "okay"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&argus_ups_pins>; /* Refer to previous label */ ++ /* This section communicates the gpio numbers to the driver module */ ++ /* Note that gpio controllers appear to be numbered from 1-n here rather than 0-(n-1)????? */ ++ gpios = <&gpio1 30 0>, /* Request */ ++ <&gpio1 5 0>, /* Acknowledge */ ++ <&gpio1 4 0>, /* Watchdog */ ++ <&gpio3 2 0>, /* LED 1 Green */ ++ <&gpio3 3 0>, /* LED 1 Red */ ++ <&gpio3 5 0>, /* LED 2 Green */ ++ <&gpio3 4 0>, /* LED 2 Red */ ++ <&gpio1 20 0>, /* General Output #1 */ ++ <&gpio1 7 0>; /* General Output #2 */ ++ debug = <0>; ++ shutdown = <1>; ++ ++ }; ++ }; ++ }; ++}; +-- +1.8.5.1 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0021-Fix-aspect-ratio-issue-of-720p-in-MT9M114-camera-cap.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0021-Fix-aspect-ratio-issue-of-720p-in-MT9M114-camera-cap.patch new file mode 100644 index 00000000..a2800cbb --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0021-Fix-aspect-ratio-issue-of-720p-in-MT9M114-camera-cap.patch @@ -0,0 +1,59 @@ +From 3dc6e3f4eb7df083896a6bc9bca0a1b745f3dc3d Mon Sep 17 00:00:00 2001 +From: Robert Nelson +Date: Thu, 2 Jan 2014 10:11:58 -0600 +Subject: [PATCH 21/21] Fix aspect ratio issue of 720p in MT9M114 camera cape + +Signed-off-by: vvdn +--- + drivers/media/i2c/soc_camera/mt9m114.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/mt9m114.c b/drivers/media/i2c/soc_camera/mt9m114.c +index 6eab204..9df2119 100644 +--- a/drivers/media/i2c/soc_camera/mt9m114.c ++++ b/drivers/media/i2c/soc_camera/mt9m114.c +@@ -411,22 +411,22 @@ static const struct mt9m114_reg mt9m114_regs_wvga[] = { + + static const struct mt9m114_reg mt9m114_regs_720p[] = { + { MT9M114_LOGICAL_ADDRESS_ACCESS, 0x1000, 2 }, +- { MT9M114_CAM_SENSOR_CFG_Y_ADDR_START, 0x0004, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_START, 0x007C, 2 }, + { MT9M114_CAM_SENSOR_CFG_X_ADDR_START, 0x0004, 2 }, +- { MT9M114_CAM_SENSOR_CFG_Y_ADDR_END, 0x03CB, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_Y_ADDR_END, 0x0353, 2 }, + { MT9M114_CAM_SENSOR_CFG_X_ADDR_END, 0x050B, 2 }, + { MT9M114_CAM_SENSOR_CFG_ROW_SPEED, 0x0001, 2 }, +- { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN, 0x00DB, 2 }, +- { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 0x05B3, 2 }, +- { MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES, 0x03EE, 2 }, +- { MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK, 0x0636, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MIN, 0x00A0, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FINE_INTEG_TIME_MAX, 0x03F7, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_FRAME_LENGTH_LINES, 0x02D5, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_LINE_LENGTH_PCK, 0x060E, 2 }, + { MT9M114_CAM_SENSOR_CFG_FINE_CORRECTION, 0x0060, 2 }, +- { MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW, 0x03C3, 2 }, ++ { MT9M114_CAM_SENSOR_CFG_CPIPE_LAST_ROW, 0x02D3, 2 }, + { MT9M114_CAM_SENSOR_CFG_REG_0_DATA, 0x0020, 2 }, + { MT9M114_CAM_CROP_WINDOW_XOFFSET, 0x0000, 2 }, + { MT9M114_CAM_CROP_WINDOW_YOFFSET, 0x0000, 2 }, + { MT9M114_CAM_CROP_WINDOW_WIDTH, 0x0500, 2 }, +- { MT9M114_CAM_CROP_WINDOW_HEIGHT, 0x03C0, 2 }, ++ { MT9M114_CAM_CROP_WINDOW_HEIGHT, 0x02D0, 2 }, + { MT9M114_CAM_CROP_CROPMODE, 0x03, 1 }, + { MT9M114_CAM_OUTPUT_WIDTH, 0x0500, 2 }, + { MT9M114_CAM_OUTPUT_HEIGHT, 0x02D0, 2 }, +@@ -437,8 +437,8 @@ static const struct mt9m114_reg mt9m114_regs_720p[] = { + { MT9M114_CAM_STAT_AWB_CLIP_WINDOW_YEND, 0x02CF, 2 }, + { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XSTART, 0x0000, 2 }, + { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YSTART, 0x0000, 2 }, +- { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND, 0x00FF, 2 }, +- { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND, 0x008F, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_XEND, 0x009F, 2 }, ++ { MT9M114_CAM_STAT_AE_INITIAL_WINDOW_YEND, 0x005F, 2 }, + }; + + static const struct mt9m114_format { +-- +1.8.5.2 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0022-beaglebone-capes-Added-overlays-for-CBB-Serial-cape.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0022-beaglebone-capes-Added-overlays-for-CBB-Serial-cape.patch new file mode 100644 index 00000000..540dbce6 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0022-beaglebone-capes-Added-overlays-for-CBB-Serial-cape.patch @@ -0,0 +1,278 @@ +From fd01a713e8ed3dd8253d37d4e0e34538700606d6 Mon Sep 17 00:00:00 2001 +From: Alexander Hiam +Date: Thu, 30 Jan 2014 11:44:05 -0500 +Subject: [PATCH 22/22] beaglebone capes: Added overlays for CBB-Serial cape + +Added main overaly for CBB-Serial BeagleBone cape, as well as separate +overlays to mux the AM335x UART2 and UART4 RTS and CTS pins to the 3.8 +branch. + +Signed-off-by: Alexander Hiam +--- + firmware/Makefile | 6 ++ + firmware/capes/BB-UART2-RTSCTS-00A0.dts | 57 +++++++++++++++++ + firmware/capes/BB-UART4-RTSCTS-00A0.dts | 57 +++++++++++++++++ + firmware/capes/cape-CBB-Serial-r01.dts | 106 ++++++++++++++++++++++++++++++++ + 4 files changed, 226 insertions(+) + create mode 100644 firmware/capes/BB-UART2-RTSCTS-00A0.dts + create mode 100644 firmware/capes/BB-UART4-RTSCTS-00A0.dts + create mode 100644 firmware/capes/cape-CBB-Serial-r01.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index ecc54d9..56b0b50 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -222,6 +222,12 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + # the Tester cape (tester-side) + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-tester-00A0.dtbo + ++# the CBB-Serial cape (tester-side) ++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ ++ cape-CBB-Serial-r01.dtbo \ ++ BB-UART2-RTSCTS-00A0.dtbo \ ++ BB-UART4-RTSCTS-00A0.dtbo ++ + # the virtual peripheral capes for the UARTs + # UART3 is not routed to the connectors, no cape for it + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ +diff --git a/firmware/capes/BB-UART2-RTSCTS-00A0.dts b/firmware/capes/BB-UART2-RTSCTS-00A0.dts +new file mode 100644 +index 0000000..bef5fff +--- /dev/null ++++ b/firmware/capes/BB-UART2-RTSCTS-00A0.dts +@@ -0,0 +1,57 @@ ++/* BB-UART2-RTSCTS-00A0.dts ++ * Written by Alexander Hiam ++ * for Logic Supply - http://logicsupply.com ++ * Jan 28, 2014 ++ * ++ * This overlay enables RTS/CTS flow control for UART2. ++ * HDMI must be disabled before enabling this overlay, see: ++ * http://www.logicsupply.com/blog/2013/07/18/disabling-the-beaglebone-black-hdmi-cape/ ++ * ++ * Copyright (c) 2014 - Logic Supply (http://logicsupply.com) ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ part-number = "BB-UART2-RTSCTS"; ++ version = "00A0"; ++ ++ exclusive-use = ++ "P8.38", /* uart2 rts */ ++ "P8.37"; /* uart2 cts */ ++ ++ fragment@0 { ++ /* Sets pinmux for flow control pins. */ ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ u2_rtscts_pins: pinmux_u2_rtscts_pins { ++ pinctrl-single,pins = < ++ 0x0c4 0x0e /* lcd_data9 - pullup | mode 6 (uart2_rtsn) */ ++ 0x0c0 0x36 /* lcd_data8 - rx enable | pullup | mode 6 (uart2_ctsn) */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ /* Enable pinmux-helper driver for setting mux configuration. */ ++ target = <&ocp>; /* On-Chip Peripherals */ ++ __overlay__ { ++ uart2-rtscts-pinmux { ++ compatible = "bone-pinmux-helper"; /* Use the pinmux helper */ ++ status="okay"; ++ /* Define custom names for indexes in pinctrl array: */ ++ pinctrl-names = "default"; ++ /* Set the elements of the pinctrl array to the pinmux overlays ++ defined above: */ ++ pinctrl-0 = <&u2_rtscts_pins>; ++ }; ++ }; ++ }; ++}; +diff --git a/firmware/capes/BB-UART4-RTSCTS-00A0.dts b/firmware/capes/BB-UART4-RTSCTS-00A0.dts +new file mode 100644 +index 0000000..a8f8e98 +--- /dev/null ++++ b/firmware/capes/BB-UART4-RTSCTS-00A0.dts +@@ -0,0 +1,57 @@ ++/* BB-UART4-RTSCTS-00A0.dts ++ * Written by Alexander Hiam ++ * for Logic Supply - http://logicsupply.com ++ * Jan 28, 2014 ++ * ++ * This overlay enables RTS/CTS flow control for UART4. ++ * HDMI must be disabled before enabling this overlay, see: ++ * http://www.logicsupply.com/blog/2013/07/18/disabling-the-beaglebone-black-hdmi-cape/ ++ * ++ * Copyright (c) 2014 - Logic Supply (http://logicsupply.com) ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ part-number = "BB-UART4-RTSCTS"; ++ version = "00A0"; ++ ++ exclusive-use = ++ "P8.33", /* uart4 rts */ ++ "P8.35"; /* uart4 cts */ ++ ++ fragment@0 { ++ /* Sets pinmux for flow control pins. */ ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ u4_rtscts_pins: pinmux_u4_rtscts_pins { ++ pinctrl-single,pins = < ++ 0x0d4 0x0e /* lcd_data13 - pullup | mode 6 (uart4_rtsn) */ ++ 0x0d0 0x36 /* lcd_data12 - rx enable | pullup | mode 6 (uart4_ctsn) */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ /* Enable pinmux-helper driver for setting mux configuration. */ ++ target = <&ocp>; /* On-Chip Peripherals */ ++ __overlay__ { ++ uart4-rtscts-pinmux { ++ compatible = "bone-pinmux-helper"; /* Use the pinmux helper */ ++ status="okay"; ++ /* Define custom names for indexes in pinctrl array: */ ++ pinctrl-names = "default"; ++ /* Set the elements of the pinctrl array to the pinmux overlays ++ defined above: */ ++ pinctrl-0 = <&u4_rtscts_pins>; ++ }; ++ }; ++ }; ++}; +diff --git a/firmware/capes/cape-CBB-Serial-r01.dts b/firmware/capes/cape-CBB-Serial-r01.dts +new file mode 100644 +index 0000000..0309bd2 +--- /dev/null ++++ b/firmware/capes/cape-CBB-Serial-r01.dts +@@ -0,0 +1,106 @@ ++/* cape-CBB-Serial-r01.dts ++ * Written by Alexander Hiam ++ * for Logic Supply - http://logicsupply.com ++ * Jan 28, 2014 ++ * ++ * This is the Device Tree overlay for the CBB-Serial BeagleBone and ++ * BeagleBone Black cape. It will enable the UART2, UART4 and DCAN1 ++ * interfaces, as well as mux GPIO1_16 for userspace control for ++ * using software control of the RS485 receiver/driver enable. ++ * ++ * Note: the BeagleBone Black has GPIO1_16 tied to GPIO2_0 (which ++ * is not exposed on the header), so this overlay muxes and controls ++ * both pins. ++ * ++ * Copyright (c) 2014 - Logic Supply (http://logicsupply.com) ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ part-number = "cape-CBB-Serial"; ++ version = "r01"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header uses */ ++ "P9.15", /* GPIO1_16 */ ++ ++ "P9.21", /* uart2_txd */ ++ "P9.22", /* uart2_rxd */ ++ ++ "P9.13", /* uart4_txd */ ++ "P9.11", /* uart4_rxd */ ++ ++ "P9.24", /* dcan1_rx */ ++ "P9.26", /* dcan1_tx */ ++ ++ /* the hardware IP uses */ ++ "gpio1_16", ++ "gpio2_0", ++ "uart2", ++ "uart4", ++ "dcan1"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ cbb_serial_uart2_pins: pinmux_cbb_serial_uart2_pins { ++ pinctrl-single,pins = < ++ 0x150 0x21 /* spi0_sclk - RX_ENABLED | MODE6 (UART2 RX) */ ++ 0x154 0x01 /* spi0_d0 - MODE6 (UART2 TX) */ ++ >; ++ }; ++ ++ cbb_serial_uart4_pins: pinmux_cbb_serial_uart4_pins { ++ pinctrl-single,pins = < ++ 0x070 0x26 /* gpmc_wait0 - RX_ENABLED | MODE6 (UART4 RX) */ ++ 0x074 0x06 /* gpmc_wpn - MODE6 (UART4 TX) */ ++ 0x040 0x2f /* gpmc_a0 - pull disabled | MODE7 (GPIO1_16) */ ++ 0x088 0x2f /* gpmc_csn3 - pull disabled | MODE7 (GPIO2_0) */ ++ >; ++ }; ++ ++ cbb_serial_dcan1_pins: pinmux_cbb_serial_dcan1_pins { ++ pinctrl-single,pins = < ++ 0x180 0x12 /* uart1_rxd - PULLUP | MODE2 (DCAN TX) */ ++ 0x184 0x32 /* uart1_txd - RX_ENABLED | PULLUP | MODE2 (DCAN1 RX) */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart3>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cbb_serial_uart2_pins>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&uart5>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cbb_serial_uart4_pins>; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&dcan1>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cbb_serial_dcan1_pins>; ++ }; ++ }; ++}; +-- +1.8.5.3 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0023-apply-htu21-patch.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0023-apply-htu21-patch.patch new file mode 100644 index 00000000..4e76e13c --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0023-apply-htu21-patch.patch @@ -0,0 +1,308 @@ +From 945690e4224aa79199ef0b5635f4b6426a99af5f Mon Sep 17 00:00:00 2001 +From: Hieu Duong +Date: Thu, 20 Mar 2014 16:21:45 -0500 +Subject: [PATCH 23/24] apply htu21 patch + +Signed-off-by: Hieu Duong +--- + Documentation/hwmon/htu21 | 46 +++++++++++ + drivers/hwmon/Kconfig | 10 +++ + drivers/hwmon/Makefile | 1 + + drivers/hwmon/htu21.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 256 insertions(+) + create mode 100644 Documentation/hwmon/htu21 + create mode 100644 drivers/hwmon/htu21.c + +diff --git a/Documentation/hwmon/htu21 b/Documentation/hwmon/htu21 +new file mode 100644 +index 0000000..f39a215 +--- /dev/null ++++ b/Documentation/hwmon/htu21 +@@ -0,0 +1,46 @@ ++Kernel driver htu21 ++=================== ++ ++Supported chips: ++ * Measurement Specialties HTU21D ++ Prefix: 'htu21' ++ Addresses scanned: none ++ Datasheet: Publicly available at the Measurement Specialties website ++ http://www.meas-spec.com/downloads/HTU21D.pdf ++ ++ ++Author: ++ William Markezana ++ ++Description ++----------- ++ ++The HTU21D is a humidity and temperature sensor in a DFN package of ++only 3 x 3 mm footprint and 0.9 mm height. ++ ++The devices communicate with the I2C protocol. All sensors are set to the ++same I2C address 0x40, so an entry with I2C_BOARD_INFO("htu21", 0x40) can ++be used in the board setup code. ++ ++This driver does not auto-detect devices. You will have to instantiate the ++devices explicitly. Please see Documentation/i2c/instantiating-devices ++for details. ++ ++sysfs-Interface ++--------------- ++ ++temp1_input - temperature input ++humidity1_input - humidity input ++ ++Notes ++----- ++ ++The driver uses the default resolution settings of 12 bit for humidity and 14 ++bit for temperature, which results in typical measurement times of 11 ms for ++humidity and 44 ms for temperature. To keep self heating below 0.1 degree ++Celsius, the device should not be active for more than 10% of the time. For ++this reason, the driver performs no more than two measurements per second and ++reports cached information if polled more frequently. ++ ++Different resolutions, the on-chip heater, using the CRC checksum and reading ++the serial number are not supported yet. +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 80bc9a5c20..4156f5e 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -470,6 +470,16 @@ config SENSORS_HIH6130 + This driver can also be built as a module. If so, the module + will be called hih6130. + ++config SENSORS_HTU21 ++ tristate "Measurement Specialties HTU21D humidity/temperature sensors" ++ depends on I2C ++ help ++ If you say yes here you get support for the Measurement Specialties ++ HTU21D humidity and temperature sensors. ++ ++ This driver can also be built as a module. If so, the module ++ will be called htu21. ++ + config SENSORS_CORETEMP + tristate "Intel Core/Core2/Atom temperature sensor" + depends on X86 +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index d8738f8..16b6d65 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o + obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o + obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o + obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o ++obj-$(CONFIG_SENSORS_HTU21) += htu21.o + obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o + obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o + obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o +diff --git a/drivers/hwmon/htu21.c b/drivers/hwmon/htu21.c +new file mode 100644 +index 0000000..839086e +--- /dev/null ++++ b/drivers/hwmon/htu21.c +@@ -0,0 +1,199 @@ ++/* ++ * Measurement Specialties HTU21D humidity and temperature sensor driver ++ * ++ * Copyright (C) 2013 William Markezana ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* HTU21 Commands */ ++#define HTU21_T_MEASUREMENT_HM 0xE3 ++#define HTU21_RH_MEASUREMENT_HM 0xE5 ++ ++struct htu21 { ++ struct device *hwmon_dev; ++ struct mutex lock; ++ bool valid; ++ unsigned long last_update; ++ int temperature; ++ int humidity; ++}; ++ ++static inline int htu21_temp_ticks_to_millicelsius(int ticks) ++{ ++ ticks &= ~0x0003; /* clear status bits */ ++ /* ++ * Formula T = -46.85 + 175.72 * ST / 2^16 from datasheet p14, ++ * optimized for integer fixed point (3 digits) arithmetic ++ */ ++ return ((21965 * ticks) >> 13) - 46850; ++} ++ ++static inline int htu21_rh_ticks_to_per_cent_mille(int ticks) ++{ ++ ticks &= ~0x0003; /* clear status bits */ ++ /* ++ * Formula RH = -6 + 125 * SRH / 2^16 from datasheet p14, ++ * optimized for integer fixed point (3 digits) arithmetic ++ */ ++ return ((15625 * ticks) >> 13) - 6000; ++} ++ ++static int htu21_update_measurements(struct i2c_client *client) ++{ ++ int ret = 0; ++ struct htu21 *htu21 = i2c_get_clientdata(client); ++ ++ mutex_lock(&htu21->lock); ++ ++ if (time_after(jiffies, htu21->last_update + HZ / 2) || ++ !htu21->valid) { ++ ret = i2c_smbus_read_word_swapped(client, ++ HTU21_T_MEASUREMENT_HM); ++ if (ret < 0) ++ goto out; ++ htu21->temperature = htu21_temp_ticks_to_millicelsius(ret); ++ ret = i2c_smbus_read_word_swapped(client, ++ HTU21_RH_MEASUREMENT_HM); ++ if (ret < 0) ++ goto out; ++ htu21->humidity = htu21_rh_ticks_to_per_cent_mille(ret); ++ htu21->last_update = jiffies; ++ htu21->valid = true; ++ } ++out: ++ mutex_unlock(&htu21->lock); ++ ++ return ret >= 0 ? 0 : ret; ++} ++ ++static ssize_t htu21_show_temperature(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct htu21 *htu21 = i2c_get_clientdata(client); ++ int ret = htu21_update_measurements(client); ++ if (ret < 0) ++ return ret; ++ return sprintf(buf, "%d\n", htu21->temperature); ++} ++ ++static ssize_t htu21_show_humidity(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct htu21 *htu21 = i2c_get_clientdata(client); ++ int ret = htu21_update_measurements(client); ++ if (ret < 0) ++ return ret; ++ return sprintf(buf, "%d\n", htu21->humidity); ++} ++ ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ++ htu21_show_temperature, NULL, 0); ++static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, ++ htu21_show_humidity, NULL, 0); ++ ++static struct attribute *htu21_attributes[] = { ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_humidity1_input.dev_attr.attr, ++ NULL ++}; ++ ++static const struct attribute_group htu21_group = { ++ .attrs = htu21_attributes, ++}; ++ ++static int htu21_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct htu21 *htu21; ++ int err; ++ ++ if (!i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_WORD_DATA)) { ++ dev_err(&client->dev, ++ "adapter does not support SMBus word transactions\n"); ++ return -ENODEV; ++ } ++ ++ htu21 = devm_kzalloc(&client->dev, sizeof(*htu21), GFP_KERNEL); ++ if (!htu21) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, htu21); ++ ++ mutex_init(&htu21->lock); ++ ++ err = sysfs_create_group(&client->dev.kobj, &htu21_group); ++ if (err) { ++ dev_dbg(&client->dev, "could not create sysfs files\n"); ++ return err; ++ } ++ htu21->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(htu21->hwmon_dev)) { ++ dev_dbg(&client->dev, "unable to register hwmon device\n"); ++ err = PTR_ERR(htu21->hwmon_dev); ++ goto error; ++ } ++ ++ dev_info(&client->dev, "initialized\n"); ++ ++ return 0; ++ ++error: ++ sysfs_remove_group(&client->dev.kobj, &htu21_group); ++ return err; ++} ++ ++static int htu21_remove(struct i2c_client *client) ++{ ++ struct htu21 *htu21 = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(htu21->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &htu21_group); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id htu21_id[] = { ++ { "htu21", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, htu21_id); ++ ++static struct i2c_driver htu21_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "htu21", ++ }, ++ .probe = htu21_probe, ++ .remove = htu21_remove, ++ .id_table = htu21_id, ++}; ++ ++module_i2c_driver(htu21_driver); ++ ++MODULE_AUTHOR("William Markezana "); ++MODULE_DESCRIPTION("MEAS HTU21D humidity and temperature sensor driver"); ++MODULE_LICENSE("GPL"); +-- +1.9.0 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0024-add-support-for-weather-cape-rev-b.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0024-add-support-for-weather-cape-rev-b.patch new file mode 100644 index 00000000..eaaab23a --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0024-add-support-for-weather-cape-rev-b.patch @@ -0,0 +1,128 @@ +From e536241681a5644be735415c6be1c0d7c1e896db Mon Sep 17 00:00:00 2001 +From: Hieu Duong +Date: Thu, 20 Mar 2014 16:31:36 -0500 +Subject: [PATCH 24/24] add support for weather cape rev b + +Signed-off-by: Hieu Duong +--- + arch/arm/boot/dts/am335x-bone-common.dtsi | 4 ++ + firmware/Makefile | 4 +- + firmware/capes/cape-bone-weather-00B0.dts | 76 +++++++++++++++++++++++++++++++ + 3 files changed, 83 insertions(+), 1 deletion(-) + create mode 100644 firmware/capes/cape-bone-weather-00B0.dts + +diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi +index c401870..4e3c475 100644 +--- a/arch/arm/boot/dts/am335x-bone-common.dtsi ++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi +@@ -309,6 +309,10 @@ + version = "00A0"; + dtbo = "cape-bone-weather-00A0.dtbo"; + }; ++ version@00B0 { ++ version = "00B0"; ++ dtbo = "cape-bone-weather-00B0.dtbo"; ++ }; + }; + + /* beaglebone black hdmi on board */ +diff --git a/firmware/Makefile b/firmware/Makefile +index 56b0b50..01314ae 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -213,7 +213,9 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += \ + cape-bone-nixie-00A0.dtbo + + # the weather cape +-fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-weather-00A0.dtbo ++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ ++ cape-bone-weather-00A0.dtbo \ ++ cape-bone-weather-00B0.dtbo + + # the HDMI virtual capes on the beaglebone-black + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ +diff --git a/firmware/capes/cape-bone-weather-00B0.dts b/firmware/capes/cape-bone-weather-00B0.dts +new file mode 100644 +index 0000000..e399cf3 +--- /dev/null ++++ b/firmware/capes/cape-bone-weather-00B0.dts +@@ -0,0 +1,76 @@ ++/* ++* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ ++* ++* This program is free software; you can redistribute it and/or modify ++* it under the terms of the GNU General Public License version 2 as ++* published by the Free Software Foundation. ++*/ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ part-number = "BB-BONE-WTHR-01"; ++ version = "00B0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header uses */ ++ "P8.6", /* gpio1_3 */ ++ /* the hardware IP uses */ ++ "gpio1_3"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ weather_cape_w1_pins: pinmux_weather_cape_w1_pins { ++ pinctrl-single,pins = < ++ 0x0c 0x37 /* gpmc_ad3.gpio1_3, OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE7 - w1-gpio */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2c2>; ++ ++ __overlay__ { ++ /* needed to avoid gripping by DTC */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* Ambient light sensor */ ++ tsl2550@39 { ++ compatible = "tsl,tsl2550"; ++ reg = <0x39>; ++ }; ++ ++ /* Humidity Sensor */ ++ htu21@40 { ++ compatible = "meas-spec,htu21"; ++ reg = <0x40>; ++ }; ++ ++ /* Barometric pressure sensor */ ++ bmp085@77 { ++ compatible = "bosch,bmp085"; ++ reg = <0x77>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&ocp>; ++ __overlay__ { ++ onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&weather_cape_w1_pins>; ++ status = "okay"; ++ ++ gpios = <&gpio2 3 0>; ++ }; ++ }; ++ }; ++}; +-- +1.9.0 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0025-capes-Add-cape-universal-overlay-files-More-details-.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0025-capes-Add-cape-universal-overlay-files-More-details-.patch new file mode 100644 index 00000000..f91bb7ca --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0025-capes-Add-cape-universal-overlay-files-More-details-.patch @@ -0,0 +1,3766 @@ +From 88ca487f0a695ec8e1261fbe9489aa0e29a99ab9 Mon Sep 17 00:00:00 2001 +From: Charles Steinkuehler +Date: Sun, 23 Mar 2014 20:13:44 +0100 +Subject: [PATCH 25/25] capes: Add cape-universal overlay files More details + and full source can be found at: + https://github.com/cdsteinkuehler/beaglebone-universal-io + +Signed-off-by: Charles Steinkuehler +--- + firmware/Makefile | 5 +- + firmware/capes/cape-univ-emmc-00A0.dts | 372 +++++++ + firmware/capes/cape-universal-00A0.dts | 1730 +++++++++++++++++++++++++++++++ + firmware/capes/cape-universaln-00A0.dts | 1609 ++++++++++++++++++++++++++++ + 4 files changed, 3715 insertions(+), 1 deletion(-) + create mode 100644 firmware/capes/cape-univ-emmc-00A0.dts + create mode 100644 firmware/capes/cape-universal-00A0.dts + create mode 100644 firmware/capes/cape-universaln-00A0.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index d767a82..4e56720 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -197,7 +197,10 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + BB-BONE-BACONE2-00A0.dtbo \ + DNIL-AMPCAPE-1-00R1.dtbo \ + cape-bone-replicape-00A2.dtbo \ +- cape-bone-replicape-00A3.dtbo ++ cape-bone-replicape-00A3.dtbo \ ++ cape-univ-emmc-00A0.dtbo \ ++ cape-universal-00A0.dtbo \ ++ cape-universaln-00A0.dtbo + + # the geiger cape + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \ +diff --git a/firmware/capes/cape-univ-emmc-00A0.dts b/firmware/capes/cape-univ-emmc-00A0.dts +new file mode 100644 +index 0000000..f4822a7 +--- /dev/null ++++ b/firmware/capes/cape-univ-emmc-00A0.dts +@@ -0,0 +1,372 @@ ++// Copyright 2013 ++// Charles Steinkuehler ++// ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; either version 2 of the License, or ++// (at your option) any later version. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with this program; if not, write to the Free Software ++// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "cape-bone-universal"; ++ version = "00A0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ ++ "P8.3", /* emmc */ ++ "P8.4", /* emmc */ ++ "P8.5", /* emmc */ ++ "P8.6", /* emmc */ ++ "P8.20", /* emmc */ ++ "P8.21", /* emmc */ ++ "P8.22", /* emmc */ ++ "P8.23", /* emmc */ ++ "P8.24", /* emmc */ ++ "P8.25"; /* emmc */ ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ /* P8_01 GND */ ++ /* P8_02 GND */ ++ /* P8_03 (ZCZ ball R9 ) emmc */ ++ P8_03_default_pin: pinmux_P8_03_default_pin { ++ pinctrl-single,pins = <0x018 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_03_gpio_pin: pinmux_P8_03_gpio_pin { ++ pinctrl-single,pins = <0x018 0x2F>; }; /* Mode 7, RxActive */ ++ P8_03_gpio_pu_pin: pinmux_P8_03_gpio_pu_pin { ++ pinctrl-single,pins = <0x018 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_03_gpio_pd_pin: pinmux_P8_03_gpio_pd_pin { ++ pinctrl-single,pins = <0x018 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_04 (ZCZ ball T9 ) emmc */ ++ P8_04_default_pin: pinmux_P8_04_default_pin { ++ pinctrl-single,pins = <0x01c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_04_gpio_pin: pinmux_P8_04_gpio_pin { ++ pinctrl-single,pins = <0x01c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_04_gpio_pu_pin: pinmux_P8_04_gpio_pu_pin { ++ pinctrl-single,pins = <0x01c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_04_gpio_pd_pin: pinmux_P8_04_gpio_pd_pin { ++ pinctrl-single,pins = <0x01c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_05 (ZCZ ball R8 ) emmc */ ++ P8_05_default_pin: pinmux_P8_05_default_pin { ++ pinctrl-single,pins = <0x008 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_05_gpio_pin: pinmux_P8_05_gpio_pin { ++ pinctrl-single,pins = <0x008 0x2F>; }; /* Mode 7, RxActive */ ++ P8_05_gpio_pu_pin: pinmux_P8_05_gpio_pu_pin { ++ pinctrl-single,pins = <0x008 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_05_gpio_pd_pin: pinmux_P8_05_gpio_pd_pin { ++ pinctrl-single,pins = <0x008 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_06 (ZCZ ball T8 ) emmc */ ++ P8_06_default_pin: pinmux_P8_06_default_pin { ++ pinctrl-single,pins = <0x00c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_06_gpio_pin: pinmux_P8_06_gpio_pin { ++ pinctrl-single,pins = <0x00c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_06_gpio_pu_pin: pinmux_P8_06_gpio_pu_pin { ++ pinctrl-single,pins = <0x00c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_06_gpio_pd_pin: pinmux_P8_06_gpio_pd_pin { ++ pinctrl-single,pins = <0x00c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ ++ /* P8_20 (ZCZ ball V9 ) emmc */ ++ P8_20_default_pin: pinmux_P8_20_default_pin { ++ pinctrl-single,pins = <0x084 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_20_gpio_pin: pinmux_P8_20_gpio_pin { ++ pinctrl-single,pins = <0x084 0x2F>; }; /* Mode 7, RxActive */ ++ P8_20_gpio_pu_pin: pinmux_P8_20_gpio_pu_pin { ++ pinctrl-single,pins = <0x084 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_20_gpio_pd_pin: pinmux_P8_20_gpio_pd_pin { ++ pinctrl-single,pins = <0x084 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_20_pruout_pin: pinmux_P8_20_pruout_pin { ++ pinctrl-single,pins = <0x084 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P8_20_pruin_pin: pinmux_P8_20_pruin_pin { ++ pinctrl-single,pins = <0x084 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ ++ /* P8_21 (ZCZ ball U9 ) emmc */ ++ P8_21_default_pin: pinmux_P8_21_default_pin { ++ pinctrl-single,pins = <0x080 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_21_gpio_pin: pinmux_P8_21_gpio_pin { ++ pinctrl-single,pins = <0x080 0x2F>; }; /* Mode 7, RxActive */ ++ P8_21_gpio_pu_pin: pinmux_P8_21_gpio_pu_pin { ++ pinctrl-single,pins = <0x080 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_21_gpio_pd_pin: pinmux_P8_21_gpio_pd_pin { ++ pinctrl-single,pins = <0x080 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_21_pruout_pin: pinmux_P8_21_pruout_pin { ++ pinctrl-single,pins = <0x080 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P8_21_pruin_pin: pinmux_P8_21_pruin_pin { ++ pinctrl-single,pins = <0x080 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P8_22 (ZCZ ball V8 ) emmc */ ++ P8_22_default_pin: pinmux_P8_22_default_pin { ++ pinctrl-single,pins = <0x014 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_22_gpio_pin: pinmux_P8_22_gpio_pin { ++ pinctrl-single,pins = <0x014 0x2F>; }; /* Mode 7, RxActive */ ++ P8_22_gpio_pu_pin: pinmux_P8_22_gpio_pu_pin { ++ pinctrl-single,pins = <0x014 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_22_gpio_pd_pin: pinmux_P8_22_gpio_pd_pin { ++ pinctrl-single,pins = <0x014 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_23 (ZCZ ball U8 ) emmc */ ++ P8_23_default_pin: pinmux_P8_23_default_pin { ++ pinctrl-single,pins = <0x010 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_23_gpio_pin: pinmux_P8_23_gpio_pin { ++ pinctrl-single,pins = <0x010 0x2F>; }; /* Mode 7, RxActive */ ++ P8_23_gpio_pu_pin: pinmux_P8_23_gpio_pu_pin { ++ pinctrl-single,pins = <0x010 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_23_gpio_pd_pin: pinmux_P8_23_gpio_pd_pin { ++ pinctrl-single,pins = <0x010 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_24 (ZCZ ball V7 ) emmc */ ++ P8_24_default_pin: pinmux_P8_24_default_pin { ++ pinctrl-single,pins = <0x004 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_24_gpio_pin: pinmux_P8_24_gpio_pin { ++ pinctrl-single,pins = <0x004 0x2F>; }; /* Mode 7, RxActive */ ++ P8_24_gpio_pu_pin: pinmux_P8_24_gpio_pu_pin { ++ pinctrl-single,pins = <0x004 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_24_gpio_pd_pin: pinmux_P8_24_gpio_pd_pin { ++ pinctrl-single,pins = <0x004 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_25 (ZCZ ball U7 ) emmc */ ++ P8_25_default_pin: pinmux_P8_25_default_pin { ++ pinctrl-single,pins = <0x000 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_25_gpio_pin: pinmux_P8_25_gpio_pin { ++ pinctrl-single,pins = <0x000 0x2F>; }; /* Mode 7, RxActive */ ++ P8_25_gpio_pu_pin: pinmux_P8_25_gpio_pu_pin { ++ pinctrl-single,pins = <0x000 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_25_gpio_pd_pin: pinmux_P8_25_gpio_pd_pin { ++ pinctrl-single,pins = <0x000 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ }; ++ }; ++ ++ ++ /************************/ ++ /* Pin Multiplexing */ ++ /************************/ ++ ++ fragment@1 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ P8_03_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_03_default_pin>; ++ pinctrl-1 = <&P8_03_gpio_pin>; ++ pinctrl-2 = <&P8_03_gpio_pu_pin>; ++ pinctrl-3 = <&P8_03_gpio_pd_pin>; ++ }; ++ ++ P8_04_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_04_default_pin>; ++ pinctrl-1 = <&P8_04_gpio_pin>; ++ pinctrl-2 = <&P8_04_gpio_pu_pin>; ++ pinctrl-3 = <&P8_04_gpio_pd_pin>; ++ }; ++ ++ P8_05_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_05_default_pin>; ++ pinctrl-1 = <&P8_05_gpio_pin>; ++ pinctrl-2 = <&P8_05_gpio_pu_pin>; ++ pinctrl-3 = <&P8_05_gpio_pd_pin>; ++ }; ++ ++ P8_06_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_06_default_pin>; ++ pinctrl-1 = <&P8_06_gpio_pin>; ++ pinctrl-2 = <&P8_06_gpio_pu_pin>; ++ pinctrl-3 = <&P8_06_gpio_pd_pin>; ++ }; ++ ++ P8_20_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_20_default_pin>; ++ pinctrl-1 = <&P8_20_gpio_pin>; ++ pinctrl-2 = <&P8_20_gpio_pu_pin>; ++ pinctrl-3 = <&P8_20_gpio_pd_pin>; ++ pinctrl-4 = <&P8_20_pruout_pin>; ++ pinctrl-5 = <&P8_20_pruin_pin>; ++ }; ++ ++ P8_21_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_21_default_pin>; ++ pinctrl-1 = <&P8_21_gpio_pin>; ++ pinctrl-2 = <&P8_21_gpio_pu_pin>; ++ pinctrl-3 = <&P8_21_gpio_pd_pin>; ++ pinctrl-4 = <&P8_21_pruout_pin>; ++ pinctrl-5 = <&P8_21_pruin_pin>; ++ }; ++ ++ P8_22_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_22_default_pin>; ++ pinctrl-1 = <&P8_22_gpio_pin>; ++ pinctrl-2 = <&P8_22_gpio_pu_pin>; ++ pinctrl-3 = <&P8_22_gpio_pd_pin>; ++ }; ++ ++ P8_23_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_23_default_pin>; ++ pinctrl-1 = <&P8_23_gpio_pin>; ++ pinctrl-2 = <&P8_23_gpio_pu_pin>; ++ pinctrl-3 = <&P8_23_gpio_pd_pin>; ++ }; ++ ++ P8_24_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_24_default_pin>; ++ pinctrl-1 = <&P8_24_gpio_pin>; ++ pinctrl-2 = <&P8_24_gpio_pu_pin>; ++ pinctrl-3 = <&P8_24_gpio_pd_pin>; ++ }; ++ ++ P8_25_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_25_default_pin>; ++ pinctrl-1 = <&P8_25_gpio_pin>; ++ pinctrl-2 = <&P8_25_gpio_pu_pin>; ++ pinctrl-3 = <&P8_25_gpio_pd_pin>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ // !!!WARNING!!! ++ // gpio-of-helper &gpio pointers are off-by-one vs. the hardware: ++ // hardware GPIO bank 0 = &gpio1 ++ cape-universal { ++ compatible = "gpio-of-helper"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ P8_03 { ++ gpio-name = "P8_03"; ++ gpio = <&gpio2 6 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_04 { ++ gpio-name = "P8_04"; ++ gpio = <&gpio2 7 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_05 { ++ gpio-name = "P8_05"; ++ gpio = <&gpio2 2 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_06 { ++ gpio-name = "P8_06"; ++ gpio = <&gpio2 3 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_20 { ++ gpio-name = "P8_20"; ++ gpio = <&gpio2 31 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_21 { ++ gpio-name = "P8_21"; ++ gpio = <&gpio2 30 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_22 { ++ gpio-name = "P8_22"; ++ gpio = <&gpio2 5 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_23 { ++ gpio-name = "P8_23"; ++ gpio = <&gpio2 4 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_24 { ++ gpio-name = "P8_24"; ++ gpio = <&gpio2 1 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_25 { ++ gpio-name = "P8_25"; ++ gpio = <&gpio2 0 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ }; ++ }; ++ }; ++ ++}; +diff --git a/firmware/capes/cape-universal-00A0.dts b/firmware/capes/cape-universal-00A0.dts +new file mode 100644 +index 0000000..e0f4e13 +--- /dev/null ++++ b/firmware/capes/cape-universal-00A0.dts +@@ -0,0 +1,1730 @@ ++// Copyright 2013 ++// Charles Steinkuehler ++// ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; either version 2 of the License, or ++// (at your option) any later version. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with this program; if not, write to the Free Software ++// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "cape-bone-universal"; ++ version = "00A0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ ++/* "P8.1", GND */ ++/* "P8.2", GND */ ++/* "P8.3", emmc */ ++/* "P8.4", emmc */ ++/* "P8.5", emmc */ ++/* "P8.6", emmc */ ++ "P8.7", ++ "P8.8", ++ "P8.9", ++ "P8.10", ++ "P8.11", ++ "P8.12", ++ "P8.13", ++ "P8.14", ++ "P8.15", ++ "P8.16", ++ "P8.17", ++ "P8.18", ++ "P8.19", ++/* "P8.20", emmc */ ++/* "P8.21", emmc */ ++/* "P8.22", emmc */ ++/* "P8.23", emmc */ ++/* "P8.24", emmc */ ++/* "P8.25", emmc */ ++ "P8.26", ++/* "P8.27", hdmi */ ++/* "P8.28", hdmi */ ++/* "P8.29", hdmi */ ++/* "P8.30", hdmi */ ++/* "P8.31", hdmi */ ++/* "P8.32", hdmi */ ++/* "P8.33", hdmi */ ++/* "P8.34", hdmi */ ++/* "P8.35", hdmi */ ++/* "P8.36", hdmi */ ++/* "P8.37", hdmi */ ++/* "P8.38", hdmi */ ++/* "P8.39", hdmi */ ++/* "P8.40", hdmi */ ++/* "P8.41", hdmi */ ++/* "P8.42", hdmi */ ++/* "P8.43", hdmi */ ++/* "P8.44", hdmi */ ++/* "P8.45", hdmi */ ++/* "P8.46", hdmi */ ++ ++/* "P9.1", GND */ ++/* "P9.2", GND */ ++/* "P9.3", 3.3V */ ++/* "P9.4", 3.3V */ ++/* "P9.5", VDD_5V */ ++/* "P9.6", VDD_5V */ ++/* "P9.7", SYS_5V */ ++/* "P9.8", SYS_5V */ ++/* "P9.9", PWR_BUT */ ++/* "P9.10", RESETn */ ++ "P9.11", ++ "P9.12", ++ "P9.13", ++ "P9.14", ++ "P9.15", ++ "P9.16", ++ "P9.17", ++ "P9.18", ++/* "P9.19", I2C */ ++/* "P9.20", I2C */ ++ "P9.21", ++ "P9.22", ++ "P9.23", ++ "P9.24", ++ "P9.25", ++ "P9.26", ++ "P9.27", ++ "P9.28", ++ "P9.29", ++ "P9.30", ++ "P9.31", ++/* "P9.32", VADC */ ++/* "P9.33", AIN4 */ ++/* "P9.34", AGND */ ++/* "P9.35", AIN6 */ ++/* "P9.36", AIN5 */ ++/* "P9.37", AIN2 */ ++/* "P9.38", AIN3 */ ++/* "P9.39", AIN0 */ ++/* "P9.40", AIN1 */ ++ "P9.41", ++ "P9.41.1", ++ "P9.42", ++ "P9.42.1", ++/* "P9.43", GND */ ++/* "P9.44", GND */ ++/* "P9.45", GND */ ++/* "P9.46", GND */ ++ ++ "uart1", ++ "uart2", ++ "uart4", ++// "uart5", /* Conflicts with HDMI */ ++ ++ "ehrpwm0A", ++ "ehrpwm0B", ++ "ehrpwm1A", ++ "ehrpwm1B", ++ "ehrpwm2A", ++ "ehrpwm2B", ++ ++// "epwmss0", ++// "ehrpwm0", ++// "ecap0", ++// "epwmss1", ++// "ehrpwm1", ++// "epwmss2", ++// "ehrpwm2", ++// "ecap2", ++ ++ "i2c1", ++ "spi1", ++ "spi0", ++ "dcan0", ++ "dcan1", ++ ++ "pru0", ++ "pru1", ++ "pruss"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ /* P8_01 GND */ ++ /* P8_02 GND */ ++ /* P8_03 (ZCZ ball R9 ) emmc */ ++ /* P8_04 (ZCZ ball T9 ) emmc */ ++ /* P8_05 (ZCZ ball R8 ) emmc */ ++ /* P8_06 (ZCZ ball T8 ) emmc */ ++ ++ /* P8_07 (ZCZ ball R7 ) */ ++ P8_07_default_pin: pinmux_P8_07_default_pin { ++ pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_07_gpio_pin: pinmux_P8_07_gpio_pin { ++ pinctrl-single,pins = <0x090 0x2F>; }; /* Mode 7, RxActive */ ++ P8_07_gpio_pu_pin: pinmux_P8_07_gpio_pu_pin { ++ pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_07_gpio_pd_pin: pinmux_P8_07_gpio_pd_pin { ++ pinctrl-single,pins = <0x090 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_07_timer_pin: pinmux_P8_07_timer_pin { ++ pinctrl-single,pins = <0x090 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ ++ /* P8_08 (ZCZ ball T7 ) */ ++ P8_08_default_pin: pinmux_P8_08_default_pin { ++ pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_08_gpio_pin: pinmux_P8_08_gpio_pin { ++ pinctrl-single,pins = <0x094 0x2F>; }; /* Mode 7, RxActive */ ++ P8_08_gpio_pu_pin: pinmux_P8_08_gpio_pu_pin { ++ pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_08_gpio_pd_pin: pinmux_P8_08_gpio_pd_pin { ++ pinctrl-single,pins = <0x094 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_08_timer_pin: pinmux_P8_08_timer_pin { ++ pinctrl-single,pins = <0x094 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ ++ /* P8_09 (ZCZ ball T6 ) */ ++ P8_09_default_pin: pinmux_P8_09_default_pin { ++ pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_09_gpio_pin: pinmux_P8_09_gpio_pin { ++ pinctrl-single,pins = <0x09c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_09_gpio_pu_pin: pinmux_P8_09_gpio_pu_pin { ++ pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_09_gpio_pd_pin: pinmux_P8_09_gpio_pd_pin { ++ pinctrl-single,pins = <0x09c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_09_timer_pin: pinmux_P8_09_timer_pin { ++ pinctrl-single,pins = <0x09c 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ ++ /* P8_10 (ZCZ ball U6 ) */ ++ P8_10_default_pin: pinmux_P8_10_default_pin { ++ pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_10_gpio_pin: pinmux_P8_10_gpio_pin { ++ pinctrl-single,pins = <0x098 0x2F>; }; /* Mode 7, RxActive */ ++ P8_10_gpio_pu_pin: pinmux_P8_10_gpio_pu_pin { ++ pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_10_gpio_pd_pin: pinmux_P8_10_gpio_pd_pin { ++ pinctrl-single,pins = <0x098 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_10_timer_pin: pinmux_P8_10_timer_pin { ++ pinctrl-single,pins = <0x098 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ ++ /* P8_11 (ZCZ ball R12) */ ++ P8_11_default_pin: pinmux_P8_11_default_pin { ++ pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_11_gpio_pin: pinmux_P8_11_gpio_pin { ++ pinctrl-single,pins = <0x034 0x2F>; }; /* Mode 7, RxActive */ ++ P8_11_gpio_pu_pin: pinmux_P8_11_gpio_pu_pin { ++ pinctrl-single,pins = <0x034 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_11_gpio_pd_pin: pinmux_P8_11_gpio_pd_pin { ++ pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_11_pruout_pin: pinmux_P8_11_pruout_pin { ++ pinctrl-single,pins = <0x034 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ P8_11_qep_pin: pinmux_P8_11_qep_pin { ++ pinctrl-single,pins = <0x034 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_12 (ZCZ ball T12) */ ++ P8_12_default_pin: pinmux_P8_12_default_pin { ++ pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_12_gpio_pin: pinmux_P8_12_gpio_pin { ++ pinctrl-single,pins = <0x030 0x2F>; }; /* Mode 7, RxActive */ ++ P8_12_gpio_pu_pin: pinmux_P8_12_gpio_pu_pin { ++ pinctrl-single,pins = <0x030 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_12_gpio_pd_pin: pinmux_P8_12_gpio_pd_pin { ++ pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_12_pruout_pin: pinmux_P8_12_pruout_pin { ++ pinctrl-single,pins = <0x030 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ P8_12_qep_pin: pinmux_P8_12_qep_pin { ++ pinctrl-single,pins = <0x030 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_13 (ZCZ ball T10) */ ++ P8_13_default_pin: pinmux_P8_13_default_pin { ++ pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_13_gpio_pin: pinmux_P8_13_gpio_pin { ++ pinctrl-single,pins = <0x024 0x2F>; }; /* Mode 7, RxActive */ ++ P8_13_gpio_pu_pin: pinmux_P8_13_gpio_pu_pin { ++ pinctrl-single,pins = <0x024 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_13_gpio_pd_pin: pinmux_P8_13_gpio_pd_pin { ++ pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_13_pwm_pin: pinmux_P8_13_pwm_pin { ++ pinctrl-single,pins = <0x024 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_14 (ZCZ ball T11) */ ++ P8_14_default_pin: pinmux_P8_14_default_pin { ++ pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_14_gpio_pin: pinmux_P8_14_gpio_pin { ++ pinctrl-single,pins = <0x028 0x2F>; }; /* Mode 7, RxActive */ ++ P8_14_gpio_pu_pin: pinmux_P8_14_gpio_pu_pin { ++ pinctrl-single,pins = <0x028 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_14_gpio_pd_pin: pinmux_P8_14_gpio_pd_pin { ++ pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_14_pwm_pin: pinmux_P8_14_pwm_pin { ++ pinctrl-single,pins = <0x028 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_15 (ZCZ ball U13) */ ++ P8_15_default_pin: pinmux_P8_15_default_pin { ++ pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_15_gpio_pin: pinmux_P8_15_gpio_pin { ++ pinctrl-single,pins = <0x03c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_15_gpio_pu_pin: pinmux_P8_15_gpio_pu_pin { ++ pinctrl-single,pins = <0x03c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_15_gpio_pd_pin: pinmux_P8_15_gpio_pd_pin { ++ pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_15_pruin_pin: pinmux_P8_15_pruin_pin { ++ pinctrl-single,pins = <0x03c 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ P8_15_qep_pin: pinmux_P8_15_qep_pin { ++ pinctrl-single,pins = <0x03c 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_16 (ZCZ ball V13) */ ++ P8_16_default_pin: pinmux_P8_16_default_pin { ++ pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_16_gpio_pin: pinmux_P8_16_gpio_pin { ++ pinctrl-single,pins = <0x038 0x2F>; }; /* Mode 7, RxActive */ ++ P8_16_gpio_pu_pin: pinmux_P8_16_gpio_pu_pin { ++ pinctrl-single,pins = <0x038 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_16_gpio_pd_pin: pinmux_P8_16_gpio_pd_pin { ++ pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_16_pruin_pin: pinmux_P8_16_pruin_pin { ++ pinctrl-single,pins = <0x038 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ P8_16_qep_pin: pinmux_P8_16_qep_pin { ++ pinctrl-single,pins = <0x038 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_17 (ZCZ ball U12) */ ++ P8_17_default_pin: pinmux_P8_17_default_pin { ++ pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_17_gpio_pin: pinmux_P8_17_gpio_pin { ++ pinctrl-single,pins = <0x02c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_17_gpio_pu_pin: pinmux_P8_17_gpio_pu_pin { ++ pinctrl-single,pins = <0x02c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_17_gpio_pd_pin: pinmux_P8_17_gpio_pd_pin { ++ pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_17_pwm_pin: pinmux_P8_17_pwm_pin { ++ pinctrl-single,pins = <0x02c 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_18 (ZCZ ball V12) */ ++ P8_18_default_pin: pinmux_P8_18_default_pin { ++ pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_18_gpio_pin: pinmux_P8_18_gpio_pin { ++ pinctrl-single,pins = <0x08c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_18_gpio_pu_pin: pinmux_P8_18_gpio_pu_pin { ++ pinctrl-single,pins = <0x08c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_18_gpio_pd_pin: pinmux_P8_18_gpio_pd_pin { ++ pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_19 (ZCZ ball U10) */ ++ P8_19_default_pin: pinmux_P8_19_default_pin { ++ pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_19_gpio_pin: pinmux_P8_19_gpio_pin { ++ pinctrl-single,pins = <0x020 0x2F>; }; /* Mode 7, RxActive */ ++ P8_19_gpio_pu_pin: pinmux_P8_19_gpio_pu_pin { ++ pinctrl-single,pins = <0x020 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_19_gpio_pd_pin: pinmux_P8_19_gpio_pd_pin { ++ pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_19_pwm_pin: pinmux_P8_19_pwm_pin { ++ pinctrl-single,pins = <0x020 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_20 (ZCZ ball V9 ) emmc */ ++ /* P8_21 (ZCZ ball U9 ) emmc */ ++ /* P8_22 (ZCZ ball V8 ) emmc */ ++ /* P8_23 (ZCZ ball U8 ) emmc */ ++ /* P8_24 (ZCZ ball V7 ) emmc */ ++ /* P8_25 (ZCZ ball U7 ) emmc */ ++ ++ /* P8_26 (ZCZ ball V6 ) */ ++ P8_26_default_pin: pinmux_P8_26_default_pin { ++ pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_26_gpio_pin: pinmux_P8_26_gpio_pin { ++ pinctrl-single,pins = <0x07c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_26_gpio_pu_pin: pinmux_P8_26_gpio_pu_pin { ++ pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_26_gpio_pd_pin: pinmux_P8_26_gpio_pd_pin { ++ pinctrl-single,pins = <0x07c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_27 (ZCZ ball U5 ) hdmi */ ++ /* P8_28 (ZCZ ball V5 ) hdmi */ ++ /* P8_29 (ZCZ ball R5 ) hdmi */ ++ /* P8_30 (ZCZ ball R6 ) hdmi */ ++ /* P8_31 (ZCZ ball V4 ) hdmi */ ++ /* P8_32 (ZCZ ball T5 ) hdmi */ ++ /* P8_33 (ZCZ ball V3 ) hdmi */ ++ /* P8_34 (ZCZ ball U4 ) hdmi */ ++ /* P8_35 (ZCZ ball V2 ) hdmi */ ++ /* P8_36 (ZCZ ball U3 ) hdmi */ ++ /* P8_37 (ZCZ ball U1 ) hdmi */ ++ /* P8_38 (ZCZ ball U2 ) hdmi */ ++ /* P8_39 (ZCZ ball T3 ) hdmi */ ++ /* P8_40 (ZCZ ball T4 ) hdmi */ ++ /* P8_41 (ZCZ ball T1 ) hdmi */ ++ /* P8_42 (ZCZ ball T2 ) hdmi */ ++ /* P8_43 (ZCZ ball R3 ) hdmi */ ++ /* P8_44 (ZCZ ball R4 ) hdmi */ ++ /* P8_45 (ZCZ ball R1 ) hdmi */ ++ /* P8_46 (ZCZ ball R2 ) hdmi */ ++ ++ ++ /************************/ ++ /* P9 Header */ ++ /************************/ ++ ++ /* P9_01 GND */ ++ /* P9_02 GND */ ++ /* P9_03 3.3V */ ++ /* P9_04 3.3V */ ++ /* P9_05 VDD_5V */ ++ /* P9_06 VDD_5V */ ++ /* P9_07 SYS_5V */ ++ /* P9_08 SYS_5V */ ++ /* P9_09 PWR_BUT */ ++ /* P9_10 (ZCZ ball A10) RESETn */ ++ ++ /* P9_11 (ZCZ ball T17) */ ++ P9_11_default_pin: pinmux_P9_11_default_pin { ++ pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_11_gpio_pin: pinmux_P9_11_gpio_pin { ++ pinctrl-single,pins = <0x070 0x2F>; }; /* Mode 7, RxActive */ ++ P9_11_gpio_pu_pin: pinmux_P9_11_gpio_pu_pin { ++ pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_11_gpio_pd_pin: pinmux_P9_11_gpio_pd_pin { ++ pinctrl-single,pins = <0x070 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_11_uart_pin: pinmux_P9_11_uart_pin { ++ pinctrl-single,pins = <0x070 0x36>; }; /* Mode 6, Pull-Up, RxActive */ ++ ++ /* P9_12 (ZCZ ball U18) */ ++ P9_12_default_pin: pinmux_P9_12_default_pin { ++ pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_12_gpio_pin: pinmux_P9_12_gpio_pin { ++ pinctrl-single,pins = <0x078 0x2F>; }; /* Mode 7, RxActive */ ++ P9_12_gpio_pu_pin: pinmux_P9_12_gpio_pu_pin { ++ pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_12_gpio_pd_pin: pinmux_P9_12_gpio_pd_pin { ++ pinctrl-single,pins = <0x078 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P9_13 (ZCZ ball U17) */ ++ P9_13_default_pin: pinmux_P9_13_default_pin { ++ pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_13_gpio_pin: pinmux_P9_13_gpio_pin { ++ pinctrl-single,pins = <0x074 0x2F>; }; /* Mode 7, RxActive */ ++ P9_13_gpio_pu_pin: pinmux_P9_13_gpio_pu_pin { ++ pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_13_gpio_pd_pin: pinmux_P9_13_gpio_pd_pin { ++ pinctrl-single,pins = <0x074 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_13_uart_pin: pinmux_P9_13_uart_pin { ++ pinctrl-single,pins = <0x074 0x36>; }; /* Mode 6, Pull-Up, RxActive */ ++ ++ /* P9_14 (ZCZ ball U14) */ ++ P9_14_default_pin: pinmux_P9_14_default_pin { ++ pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_14_gpio_pin: pinmux_P9_14_gpio_pin { ++ pinctrl-single,pins = <0x048 0x2F>; }; /* Mode 7, RxActive */ ++ P9_14_gpio_pu_pin: pinmux_P9_14_gpio_pu_pin { ++ pinctrl-single,pins = <0x048 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_14_gpio_pd_pin: pinmux_P9_14_gpio_pd_pin { ++ pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_14_pwm_pin: pinmux_P9_14_pwm_pin { ++ pinctrl-single,pins = <0x048 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_15 (ZCZ ball R13) */ ++ P9_15_default_pin: pinmux_P9_15_default_pin { ++ pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_15_gpio_pin: pinmux_P9_15_gpio_pin { ++ pinctrl-single,pins = <0x040 0x2F>; }; /* Mode 7, RxActive */ ++ P9_15_gpio_pu_pin: pinmux_P9_15_gpio_pu_pin { ++ pinctrl-single,pins = <0x040 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_15_gpio_pd_pin: pinmux_P9_15_gpio_pd_pin { ++ pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_15_pwm_pin: pinmux_P9_15_pwm_pin { ++ pinctrl-single,pins = <0x040 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_16 (ZCZ ball T14) */ ++ P9_16_default_pin: pinmux_P9_16_default_pin { ++ pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_16_gpio_pin: pinmux_P9_16_gpio_pin { ++ pinctrl-single,pins = <0x04c 0x2F>; }; /* Mode 7, RxActive */ ++ P9_16_gpio_pu_pin: pinmux_P9_16_gpio_pu_pin { ++ pinctrl-single,pins = <0x04c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_16_gpio_pd_pin: pinmux_P9_16_gpio_pd_pin { ++ pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_16_pwm_pin: pinmux_P9_16_pwm_pin { ++ pinctrl-single,pins = <0x04c 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_17 (ZCZ ball A16) */ ++ P9_17_default_pin: pinmux_P9_17_default_pin { ++ pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_17_gpio_pin: pinmux_P9_17_gpio_pin { ++ pinctrl-single,pins = <0x15c 0x2F>; }; /* Mode 7, RxActive */ ++ P9_17_gpio_pu_pin: pinmux_P9_17_gpio_pu_pin { ++ pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_17_gpio_pd_pin: pinmux_P9_17_gpio_pd_pin { ++ pinctrl-single,pins = <0x15c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_17_spi_pin: pinmux_P9_17_spi_pin { ++ pinctrl-single,pins = <0x15c 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_17_i2c_pin: pinmux_P9_17_i2c_pin { ++ pinctrl-single,pins = <0x15c 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_17_pwm_pin: pinmux_P9_17_pwm_pin { ++ pinctrl-single,pins = <0x15c 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ ++ /* P9_18 (ZCZ ball B16) */ ++ P9_18_default_pin: pinmux_P9_18_default_pin { ++ pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_18_gpio_pin: pinmux_P9_18_gpio_pin { ++ pinctrl-single,pins = <0x158 0x2F>; }; /* Mode 7, RxActive */ ++ P9_18_gpio_pu_pin: pinmux_P9_18_gpio_pu_pin { ++ pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_18_gpio_pd_pin: pinmux_P9_18_gpio_pd_pin { ++ pinctrl-single,pins = <0x158 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_18_spi_pin: pinmux_P9_18_spi_pin { ++ pinctrl-single,pins = <0x158 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_18_i2c_pin: pinmux_P9_18_i2c_pin { ++ pinctrl-single,pins = <0x158 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_18_pwm_pin: pinmux_P9_18_pwm_pin { ++ pinctrl-single,pins = <0x158 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ ++ // Leave the cape I2C EEPROM bus alone ++ /* P9_19 (ZCZ ball D17) I2C */ ++ /* P9_20 (ZCZ ball D18) I2C */ ++ ++ /* P9_21 (ZCZ ball B17) */ ++ P9_21_default_pin: pinmux_P9_21_default_pin { ++ pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_21_gpio_pin: pinmux_P9_21_gpio_pin { ++ pinctrl-single,pins = <0x154 0x2F>; }; /* Mode 7, RxActive */ ++ P9_21_gpio_pu_pin: pinmux_P9_21_gpio_pu_pin { ++ pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_21_gpio_pd_pin: pinmux_P9_21_gpio_pd_pin { ++ pinctrl-single,pins = <0x154 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_21_spi_pin: pinmux_P9_21_spi_pin { ++ pinctrl-single,pins = <0x154 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_21_uart_pin: pinmux_P9_21_uart_pin { ++ pinctrl-single,pins = <0x154 0x31>; }; /* Mode 1, Pull-Up, RxActive */ ++ P9_21_i2c_pin: pinmux_P9_21_i2c_pin { ++ pinctrl-single,pins = <0x154 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_21_pwm_pin: pinmux_P9_21_pwm_pin { ++ pinctrl-single,pins = <0x154 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ ++ /* P9_22 (ZCZ ball A17) */ ++ P9_22_default_pin: pinmux_P9_22_default_pin { ++ pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_22_gpio_pin: pinmux_P9_22_gpio_pin { ++ pinctrl-single,pins = <0x150 0x2F>; }; /* Mode 7, RxActive */ ++ P9_22_gpio_pu_pin: pinmux_P9_22_gpio_pu_pin { ++ pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_22_gpio_pd_pin: pinmux_P9_22_gpio_pd_pin { ++ pinctrl-single,pins = <0x150 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_22_spi_pin: pinmux_P9_22_spi_pin { ++ pinctrl-single,pins = <0x150 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_22_uart_pin: pinmux_P9_22_uart_pin { ++ pinctrl-single,pins = <0x150 0x31>; }; /* Mode 1, Pull-Up, RxActive */ ++ P9_22_i2c_pin: pinmux_P9_22_i2c_pin { ++ pinctrl-single,pins = <0x150 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_22_pwm_pin: pinmux_P9_22_pwm_pin { ++ pinctrl-single,pins = <0x150 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ ++ /* P9_23 (ZCZ ball V14) */ ++ P9_23_default_pin: pinmux_P9_23_default_pin { ++ pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_23_gpio_pin: pinmux_P9_23_gpio_pin { ++ pinctrl-single,pins = <0x044 0x2F>; }; /* Mode 7, RxActive */ ++ P9_23_gpio_pu_pin: pinmux_P9_23_gpio_pu_pin { ++ pinctrl-single,pins = <0x044 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_23_gpio_pd_pin: pinmux_P9_23_gpio_pd_pin { ++ pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_23_pwm_pin: pinmux_P9_23_pwm_pin { ++ pinctrl-single,pins = <0x044 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_24 (ZCZ ball D15) */ ++ P9_24_default_pin: pinmux_P9_24_default_pin { ++ pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_24_gpio_pin: pinmux_P9_24_gpio_pin { ++ pinctrl-single,pins = <0x184 0x2F>; }; /* Mode 7, RxActive */ ++ P9_24_gpio_pu_pin: pinmux_P9_24_gpio_pu_pin { ++ pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_24_gpio_pd_pin: pinmux_P9_24_gpio_pd_pin { ++ pinctrl-single,pins = <0x184 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_24_uart_pin: pinmux_P9_24_uart_pin { ++ pinctrl-single,pins = <0x184 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_24_can_pin: pinmux_P9_24_can_pin { ++ pinctrl-single,pins = <0x184 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_24_i2c_pin: pinmux_P9_24_i2c_pin { ++ pinctrl-single,pins = <0x184 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ P9_24_pruin_pin: pinmux_P9_24_pruin_pin { ++ pinctrl-single,pins = <0x184 0x36>; }; /* Mode 6, Pull-Up, RxActive */ ++ ++ /* P9_25 (ZCZ ball A14) Audio */ ++ P9_25_default_pin: pinmux_P9_25_default_pin { ++ pinctrl-single,pins = <0x1ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_25_gpio_pin: pinmux_P9_25_gpio_pin { ++ pinctrl-single,pins = <0x1ac 0x2F>; }; /* Mode 7, RxActive */ ++ P9_25_gpio_pu_pin: pinmux_P9_25_gpio_pu_pin { ++ pinctrl-single,pins = <0x1ac 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_25_gpio_pd_pin: pinmux_P9_25_gpio_pd_pin { ++ pinctrl-single,pins = <0x1ac 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_25_qep_pin: pinmux_P9_25_qep_pin { ++ pinctrl-single,pins = <0x1ac 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_25_pruout_pin: pinmux_P9_25_pruout_pin { ++ pinctrl-single,pins = <0x1ac 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_25_pruin_pin: pinmux_P9_25_pruin_pin { ++ pinctrl-single,pins = <0x1ac 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_26 (ZCZ ball D16) */ ++ P9_26_default_pin: pinmux_P9_26_default_pin { ++ pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_26_gpio_pin: pinmux_P9_26_gpio_pin { ++ pinctrl-single,pins = <0x180 0x2F>; }; /* Mode 7, RxActive */ ++ P9_26_gpio_pu_pin: pinmux_P9_26_gpio_pu_pin { ++ pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_26_gpio_pd_pin: pinmux_P9_26_gpio_pd_pin { ++ pinctrl-single,pins = <0x180 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_26_uart_pin: pinmux_P9_26_uart_pin { ++ pinctrl-single,pins = <0x180 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_26_can_pin: pinmux_P9_26_can_pin { ++ pinctrl-single,pins = <0x180 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_26_i2c_pin: pinmux_P9_26_i2c_pin { ++ pinctrl-single,pins = <0x180 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ P9_26_pruin_pin: pinmux_P9_26_pruin_pin { ++ pinctrl-single,pins = <0x180 0x36>; }; /* Mode 6, Pull-Up, RxActive */ ++ ++ /* P9_27 (ZCZ ball C13) */ ++ P9_27_default_pin: pinmux_P9_27_default_pin { ++ pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_27_gpio_pin: pinmux_P9_27_gpio_pin { ++ pinctrl-single,pins = <0x1a4 0x2F>; }; /* Mode 7, RxActive */ ++ P9_27_gpio_pu_pin: pinmux_P9_27_gpio_pu_pin { ++ pinctrl-single,pins = <0x1a4 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_27_gpio_pd_pin: pinmux_P9_27_gpio_pd_pin { ++ pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_27_qep_pin: pinmux_P9_27_qep_pin { ++ pinctrl-single,pins = <0x1a4 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_27_pruout_pin: pinmux_P9_27_pruout_pin { ++ pinctrl-single,pins = <0x1a4 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_27_pruin_pin: pinmux_P9_27_pruin_pin { ++ pinctrl-single,pins = <0x1a4 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_28 (ZCZ ball C12) Audio */ ++ P9_28_default_pin: pinmux_P9_28_default_pin { ++ pinctrl-single,pins = <0x19c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_28_gpio_pin: pinmux_P9_28_gpio_pin { ++ pinctrl-single,pins = <0x19c 0x2F>; }; /* Mode 7, RxActive */ ++ P9_28_gpio_pu_pin: pinmux_P9_28_gpio_pu_pin { ++ pinctrl-single,pins = <0x19c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_28_gpio_pd_pin: pinmux_P9_28_gpio_pd_pin { ++ pinctrl-single,pins = <0x19c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_28_pwm_pin: pinmux_P9_28_pwm_pin { ++ pinctrl-single,pins = <0x19c 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_28_spi_pin: pinmux_P9_28_spi_pin { ++ pinctrl-single,pins = <0x19c 0x23>; }; /* Mode 3, Pull-Down, RxActive */ ++ P9_28_pwm2_pin: pinmux_P9_28_pwm2_pin { ++ pinctrl-single,pins = <0x19c 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ P9_28_pruout_pin: pinmux_P9_28_pruout_pin { ++ pinctrl-single,pins = <0x19c 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_28_pruin_pin: pinmux_P9_28_pruin_pin { ++ pinctrl-single,pins = <0x19c 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_29 (ZCZ ball B13) Audio */ ++ P9_29_default_pin: pinmux_P9_29_default_pin { ++ pinctrl-single,pins = <0x194 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_29_gpio_pin: pinmux_P9_29_gpio_pin { ++ pinctrl-single,pins = <0x194 0x2F>; }; /* Mode 7, RxActive */ ++ P9_29_gpio_pu_pin: pinmux_P9_29_gpio_pu_pin { ++ pinctrl-single,pins = <0x194 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_29_gpio_pd_pin: pinmux_P9_29_gpio_pd_pin { ++ pinctrl-single,pins = <0x194 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_29_pwm_pin: pinmux_P9_29_pwm_pin { ++ pinctrl-single,pins = <0x194 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_29_spi_pin: pinmux_P9_29_spi_pin { ++ pinctrl-single,pins = <0x194 0x23>; }; /* Mode 3, Pull-Down, RxActive */ ++ P9_29_pruout_pin: pinmux_P9_29_pruout_pin { ++ pinctrl-single,pins = <0x194 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_29_pruin_pin: pinmux_P9_29_pruin_pin { ++ pinctrl-single,pins = <0x194 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_30 (ZCZ ball D12) */ ++ P9_30_default_pin: pinmux_P9_30_default_pin { ++ pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_30_gpio_pin: pinmux_P9_30_gpio_pin { ++ pinctrl-single,pins = <0x198 0x2F>; }; /* Mode 7, RxActive */ ++ P9_30_gpio_pu_pin: pinmux_P9_30_gpio_pu_pin { ++ pinctrl-single,pins = <0x198 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_30_gpio_pd_pin: pinmux_P9_30_gpio_pd_pin { ++ pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_30_pwm_pin: pinmux_P9_30_pwm_pin { ++ pinctrl-single,pins = <0x198 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_30_spi_pin: pinmux_P9_30_spi_pin { ++ pinctrl-single,pins = <0x198 0x23>; }; /* Mode 3, Pull-Down, RxActive */ ++ P9_30_pruout_pin: pinmux_P9_30_pruout_pin { ++ pinctrl-single,pins = <0x198 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_30_pruin_pin: pinmux_P9_30_pruin_pin { ++ pinctrl-single,pins = <0x198 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_31 (ZCZ ball A13) Audio */ ++ P9_31_default_pin: pinmux_P9_31_default_pin { ++ pinctrl-single,pins = <0x190 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_31_gpio_pin: pinmux_P9_31_gpio_pin { ++ pinctrl-single,pins = <0x190 0x2F>; }; /* Mode 7, RxActive */ ++ P9_31_gpio_pu_pin: pinmux_P9_31_gpio_pu_pin { ++ pinctrl-single,pins = <0x190 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_31_gpio_pd_pin: pinmux_P9_31_gpio_pd_pin { ++ pinctrl-single,pins = <0x190 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_31_pwm_pin: pinmux_P9_31_pwm_pin { ++ pinctrl-single,pins = <0x190 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_31_spi_pin: pinmux_P9_31_spi_pin { ++ pinctrl-single,pins = <0x190 0x23>; }; /* Mode 3, Pull-Down, RxActive */ ++ P9_31_pruout_pin: pinmux_P9_31_pruout_pin { ++ pinctrl-single,pins = <0x190 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_31_pruin_pin: pinmux_P9_31_pruin_pin { ++ pinctrl-single,pins = <0x190 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_32 VADC */ ++ /* P9_33 (ZCZ ball C8 ) AIN4 */ ++ /* P9_34 AGND */ ++ /* P9_35 (ZCZ ball A8 ) AIN6 */ ++ /* P9_36 (ZCZ ball B8 ) AIN5 */ ++ /* P9_37 (ZCZ ball B7 ) AIN2 */ ++ /* P9_38 (ZCZ ball A7 ) AIN3 */ ++ /* P9_39 (ZCZ ball B6 ) AIN0 */ ++ /* P9_40 (ZCZ ball C7 ) AIN1 */ ++ ++ /* P9_41 (ZCZ ball D14) */ ++ P9_41_default_pin: pinmux_P9_41_default_pin { ++ pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_41_gpio_pin: pinmux_P9_41_gpio_pin { ++ pinctrl-single,pins = <0x1b4 0x2F>; }; /* Mode 7, RxActive */ ++ P9_41_gpio_pu_pin: pinmux_P9_41_gpio_pu_pin { ++ pinctrl-single,pins = <0x1b4 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_41_gpio_pd_pin: pinmux_P9_41_gpio_pd_pin { ++ pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_41_timer_pin: pinmux_P9_41_timer_pin { ++ pinctrl-single,pins = <0x1b4 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ P9_41_pruin_pin: pinmux_P9_41_pruin_pin { ++ pinctrl-single,pins = <0x1b4 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ ++ /* P9_41.1 */ ++ /* P9_91 (ZCZ ball D13) */ ++ P9_91_default_pin: pinmux_P9_91_default_pin { ++ pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_91_gpio_pin: pinmux_P9_91_gpio_pin { ++ pinctrl-single,pins = <0x1a8 0x2F>; }; /* Mode 7, RxActive */ ++ P9_91_gpio_pu_pin: pinmux_P9_91_gpio_pu_pin { ++ pinctrl-single,pins = <0x1a8 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_91_gpio_pd_pin: pinmux_P9_91_gpio_pd_pin { ++ pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_91_qep_pin: pinmux_P9_91_qep_pin { ++ pinctrl-single,pins = <0x1a8 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_91_pruout_pin: pinmux_P9_91_pruout_pin { ++ pinctrl-single,pins = <0x1a8 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_91_pruin_pin: pinmux_P9_91_pruin_pin { ++ pinctrl-single,pins = <0x1a8 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_42 (ZCZ ball C18) */ ++ P9_42_default_pin: pinmux_P9_42_default_pin { ++ pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_42_gpio_pin: pinmux_P9_42_gpio_pin { ++ pinctrl-single,pins = <0x164 0x2F>; }; /* Mode 7, RxActive */ ++ P9_42_gpio_pu_pin: pinmux_P9_42_gpio_pu_pin { ++ pinctrl-single,pins = <0x164 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_42_gpio_pd_pin: pinmux_P9_42_gpio_pd_pin { ++ pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_42_pwm_pin: pinmux_P9_42_pwm_pin { ++ pinctrl-single,pins = <0x164 0x20>; }; /* Mode 0, Pull-Down, RxActive */ ++ P9_42_uart_pin: pinmux_P9_42_uart_pin { ++ pinctrl-single,pins = <0x164 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_42_spics_pin: pinmux_P9_42_spics_pin { ++ pinctrl-single,pins = <0x164 0x22>; }; /* Mode 2, Pull-Down, RxActive */ ++ P9_42_spiclk_pin: pinmux_P9_42_spiclk_pin { ++ pinctrl-single,pins = <0x164 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P9_42.1 */ ++ /* P9_92 (ZCZ ball B12) */ ++ P9_92_default_pin: pinmux_P9_92_default_pin { ++ pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_92_gpio_pin: pinmux_P9_92_gpio_pin { ++ pinctrl-single,pins = <0x1a0 0x2F>; }; /* Mode 7, RxActive */ ++ P9_92_gpio_pu_pin: pinmux_P9_92_gpio_pu_pin { ++ pinctrl-single,pins = <0x1a0 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_92_gpio_pd_pin: pinmux_P9_92_gpio_pd_pin { ++ pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_92_qep_pin: pinmux_P9_92_qep_pin { ++ pinctrl-single,pins = <0x1a0 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_92_pruout_pin: pinmux_P9_92_pruout_pin { ++ pinctrl-single,pins = <0x1a0 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_92_pruin_pin: pinmux_P9_92_pruin_pin { ++ pinctrl-single,pins = <0x1a0 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_43 GND */ ++ /* P9_44 GND */ ++ /* P9_45 GND */ ++ /* P9_46 GND */ ++ ++ }; ++ }; ++ ++ ++ /************************/ ++ /* Pin Multiplexing */ ++ /************************/ ++ ++ fragment@1 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ P8_07_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_07_default_pin>; ++ pinctrl-1 = <&P8_07_gpio_pin>; ++ pinctrl-2 = <&P8_07_gpio_pu_pin>; ++ pinctrl-3 = <&P8_07_gpio_pd_pin>; ++ pinctrl-4 = <&P8_07_timer_pin>; ++ }; ++ ++ P8_08_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_08_default_pin>; ++ pinctrl-1 = <&P8_08_gpio_pin>; ++ pinctrl-2 = <&P8_08_gpio_pu_pin>; ++ pinctrl-3 = <&P8_08_gpio_pd_pin>; ++ pinctrl-4 = <&P8_08_timer_pin>; ++ }; ++ ++ P8_09_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_09_default_pin>; ++ pinctrl-1 = <&P8_09_gpio_pin>; ++ pinctrl-2 = <&P8_09_gpio_pu_pin>; ++ pinctrl-3 = <&P8_09_gpio_pd_pin>; ++ pinctrl-4 = <&P8_09_timer_pin>; ++ }; ++ ++ P8_10_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_10_default_pin>; ++ pinctrl-1 = <&P8_10_gpio_pin>; ++ pinctrl-2 = <&P8_10_gpio_pu_pin>; ++ pinctrl-3 = <&P8_10_gpio_pd_pin>; ++ pinctrl-4 = <&P8_10_timer_pin>; ++ }; ++ ++ P8_11_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "qep"; ++ pinctrl-0 = <&P8_11_default_pin>; ++ pinctrl-1 = <&P8_11_gpio_pin>; ++ pinctrl-2 = <&P8_11_gpio_pu_pin>; ++ pinctrl-3 = <&P8_11_gpio_pd_pin>; ++ pinctrl-4 = <&P8_11_pruout_pin>; ++ pinctrl-5 = <&P8_11_qep_pin>; ++ }; ++ ++ P8_12_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "qep"; ++ pinctrl-0 = <&P8_12_default_pin>; ++ pinctrl-1 = <&P8_12_gpio_pin>; ++ pinctrl-2 = <&P8_12_gpio_pu_pin>; ++ pinctrl-3 = <&P8_12_gpio_pd_pin>; ++ pinctrl-4 = <&P8_12_pruout_pin>; ++ pinctrl-5 = <&P8_12_qep_pin>; ++ }; ++ ++ P8_13_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_13_default_pin>; ++ pinctrl-1 = <&P8_13_gpio_pin>; ++ pinctrl-2 = <&P8_13_gpio_pu_pin>; ++ pinctrl-3 = <&P8_13_gpio_pd_pin>; ++ pinctrl-4 = <&P8_13_pwm_pin>; ++ }; ++ ++ P8_14_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_14_default_pin>; ++ pinctrl-1 = <&P8_14_gpio_pin>; ++ pinctrl-2 = <&P8_14_gpio_pu_pin>; ++ pinctrl-3 = <&P8_14_gpio_pd_pin>; ++ pinctrl-4 = <&P8_14_pwm_pin>; ++ }; ++ ++ P8_15_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin", "qep"; ++ pinctrl-0 = <&P8_15_default_pin>; ++ pinctrl-1 = <&P8_15_gpio_pin>; ++ pinctrl-2 = <&P8_15_gpio_pu_pin>; ++ pinctrl-3 = <&P8_15_gpio_pd_pin>; ++ pinctrl-4 = <&P8_15_pruin_pin>; ++ pinctrl-5 = <&P8_15_qep_pin>; ++ }; ++ ++ P8_16_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin", "qep"; ++ pinctrl-0 = <&P8_16_default_pin>; ++ pinctrl-1 = <&P8_16_gpio_pin>; ++ pinctrl-2 = <&P8_16_gpio_pu_pin>; ++ pinctrl-3 = <&P8_16_gpio_pd_pin>; ++ pinctrl-4 = <&P8_16_pruin_pin>; ++ pinctrl-5 = <&P8_16_qep_pin>; ++ }; ++ ++ P8_17_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_17_default_pin>; ++ pinctrl-1 = <&P8_17_gpio_pin>; ++ pinctrl-2 = <&P8_17_gpio_pu_pin>; ++ pinctrl-3 = <&P8_17_gpio_pd_pin>; ++ pinctrl-4 = <&P8_17_pwm_pin>; ++ }; ++ ++ P8_18_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio"; ++ pinctrl-0 = <&P8_18_default_pin>; ++ pinctrl-1 = <&P8_18_gpio_pin>; ++ pinctrl-2 = <&P8_18_gpio_pu_pin>; ++ pinctrl-3 = <&P8_18_gpio_pd_pin>; ++ }; ++ ++ P8_19_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_19_default_pin>; ++ pinctrl-1 = <&P8_19_gpio_pin>; ++ pinctrl-2 = <&P8_19_gpio_pu_pin>; ++ pinctrl-3 = <&P8_19_gpio_pd_pin>; ++ pinctrl-4 = <&P8_19_pwm_pin>; ++ }; ++ ++ P8_26_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio"; ++ pinctrl-0 = <&P8_26_default_pin>; ++ pinctrl-1 = <&P8_26_gpio_pin>; ++ pinctrl-2 = <&P8_26_gpio_pu_pin>; ++ pinctrl-3 = <&P8_26_gpio_pd_pin>; ++ }; ++ ++ ++ /************************/ ++ /* P9 Header */ ++ /************************/ ++ ++ P9_11_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; ++ pinctrl-0 = <&P9_11_default_pin>; ++ pinctrl-1 = <&P9_11_gpio_pin>; ++ pinctrl-2 = <&P9_11_gpio_pu_pin>; ++ pinctrl-3 = <&P9_11_gpio_pd_pin>; ++ pinctrl-4 = <&P9_11_uart_pin>; ++ }; ++ ++ P9_12_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio"; ++ pinctrl-0 = <&P9_12_default_pin>; ++ pinctrl-1 = <&P9_12_gpio_pin>; ++ pinctrl-2 = <&P9_12_gpio_pu_pin>; ++ pinctrl-3 = <&P9_12_gpio_pd_pin>; ++ }; ++ ++ P9_13_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; ++ pinctrl-0 = <&P9_13_default_pin>; ++ pinctrl-1 = <&P9_13_gpio_pin>; ++ pinctrl-2 = <&P9_13_gpio_pu_pin>; ++ pinctrl-3 = <&P9_13_gpio_pd_pin>; ++ pinctrl-4 = <&P9_13_uart_pin>; ++ }; ++ ++ P9_14_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_14_default_pin>; ++ pinctrl-1 = <&P9_14_gpio_pin>; ++ pinctrl-2 = <&P9_14_gpio_pu_pin>; ++ pinctrl-3 = <&P9_14_gpio_pd_pin>; ++ pinctrl-4 = <&P9_14_pwm_pin>; ++ }; ++ ++ P9_15_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_15_default_pin>; ++ pinctrl-1 = <&P9_15_gpio_pin>; ++ pinctrl-2 = <&P9_15_gpio_pu_pin>; ++ pinctrl-3 = <&P9_15_gpio_pd_pin>; ++ pinctrl-4 = <&P9_15_pwm_pin>; ++ }; ++ ++ P9_16_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_16_default_pin>; ++ pinctrl-1 = <&P9_16_gpio_pin>; ++ pinctrl-2 = <&P9_16_gpio_pu_pin>; ++ pinctrl-3 = <&P9_16_gpio_pd_pin>; ++ pinctrl-4 = <&P9_16_pwm_pin>; ++ }; ++ ++ P9_17_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm"; ++ pinctrl-0 = <&P9_17_default_pin>; ++ pinctrl-1 = <&P9_17_gpio_pin>; ++ pinctrl-2 = <&P9_17_gpio_pu_pin>; ++ pinctrl-3 = <&P9_17_gpio_pd_pin>; ++ pinctrl-4 = <&P9_17_spi_pin>; ++ pinctrl-5 = <&P9_17_i2c_pin>; ++ pinctrl-6 = <&P9_17_pwm_pin>; ++ }; ++ ++ P9_18_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm"; ++ pinctrl-0 = <&P9_18_default_pin>; ++ pinctrl-1 = <&P9_18_gpio_pin>; ++ pinctrl-2 = <&P9_18_gpio_pu_pin>; ++ pinctrl-3 = <&P9_18_gpio_pd_pin>; ++ pinctrl-4 = <&P9_18_spi_pin>; ++ pinctrl-5 = <&P9_18_i2c_pin>; ++ pinctrl-6 = <&P9_18_pwm_pin>; ++ }; ++ ++ // I2C Pins ++ // P9_19_pinmux ++ // P9_20_pinmux ++ ++ P9_21_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm"; ++ pinctrl-0 = <&P9_21_default_pin>; ++ pinctrl-1 = <&P9_21_gpio_pin>; ++ pinctrl-2 = <&P9_21_gpio_pu_pin>; ++ pinctrl-3 = <&P9_21_gpio_pd_pin>; ++ pinctrl-4 = <&P9_21_spi_pin>; ++ pinctrl-5 = <&P9_21_uart_pin>; ++ pinctrl-6 = <&P9_21_i2c_pin>; ++ pinctrl-7 = <&P9_21_pwm_pin>; ++ }; ++ ++ P9_22_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm"; ++ pinctrl-0 = <&P9_22_default_pin>; ++ pinctrl-1 = <&P9_22_gpio_pin>; ++ pinctrl-2 = <&P9_22_gpio_pu_pin>; ++ pinctrl-3 = <&P9_22_gpio_pd_pin>; ++ pinctrl-4 = <&P9_22_spi_pin>; ++ pinctrl-5 = <&P9_22_uart_pin>; ++ pinctrl-6 = <&P9_22_i2c_pin>; ++ pinctrl-7 = <&P9_22_pwm_pin>; ++ }; ++ ++ P9_23_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_23_default_pin>; ++ pinctrl-1 = <&P9_23_gpio_pin>; ++ pinctrl-2 = <&P9_23_gpio_pu_pin>; ++ pinctrl-3 = <&P9_23_gpio_pd_pin>; ++ pinctrl-4 = <&P9_23_pwm_pin>; ++ }; ++ ++ P9_24_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin"; ++ pinctrl-0 = <&P9_24_default_pin>; ++ pinctrl-1 = <&P9_24_gpio_pin>; ++ pinctrl-2 = <&P9_24_gpio_pu_pin>; ++ pinctrl-3 = <&P9_24_gpio_pd_pin>; ++ pinctrl-4 = <&P9_24_uart_pin>; ++ pinctrl-5 = <&P9_24_can_pin>; ++ pinctrl-6 = <&P9_24_i2c_pin>; ++ pinctrl-7 = <&P9_24_pruin_pin>; ++ }; ++ ++ P9_25_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_25_default_pin>; ++ pinctrl-1 = <&P9_25_gpio_pin>; ++ pinctrl-2 = <&P9_25_gpio_pu_pin>; ++ pinctrl-3 = <&P9_25_gpio_pd_pin>; ++ pinctrl-4 = <&P9_25_qep_pin>; ++ pinctrl-5 = <&P9_25_pruout_pin>; ++ pinctrl-6 = <&P9_25_pruin_pin>; ++ }; ++ ++ P9_26_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin"; ++ pinctrl-0 = <&P9_26_default_pin>; ++ pinctrl-1 = <&P9_26_gpio_pin>; ++ pinctrl-2 = <&P9_26_gpio_pu_pin>; ++ pinctrl-3 = <&P9_26_gpio_pd_pin>; ++ pinctrl-4 = <&P9_26_uart_pin>; ++ pinctrl-5 = <&P9_26_can_pin>; ++ pinctrl-6 = <&P9_26_i2c_pin>; ++ pinctrl-7 = <&P9_26_pruin_pin>; ++ }; ++ ++ P9_27_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_27_default_pin>; ++ pinctrl-1 = <&P9_27_gpio_pin>; ++ pinctrl-2 = <&P9_27_gpio_pu_pin>; ++ pinctrl-3 = <&P9_27_gpio_pd_pin>; ++ pinctrl-4 = <&P9_27_qep_pin>; ++ pinctrl-5 = <&P9_27_pruout_pin>; ++ pinctrl-6 = <&P9_27_pruin_pin>; ++ }; ++ ++ P9_28_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pwm2", "pruout", "pruin"; ++ pinctrl-0 = <&P9_28_default_pin>; ++ pinctrl-1 = <&P9_28_gpio_pin>; ++ pinctrl-2 = <&P9_28_gpio_pu_pin>; ++ pinctrl-3 = <&P9_28_gpio_pd_pin>; ++ pinctrl-4 = <&P9_28_pwm_pin>; ++ pinctrl-5 = <&P9_28_spi_pin>; ++ pinctrl-6 = <&P9_28_pwm2_pin>; ++ pinctrl-7 = <&P9_28_pruout_pin>; ++ pinctrl-8 = <&P9_28_pruin_pin>; ++ }; ++ ++ P9_29_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin"; ++ pinctrl-0 = <&P9_29_default_pin>; ++ pinctrl-1 = <&P9_29_gpio_pin>; ++ pinctrl-2 = <&P9_29_gpio_pu_pin>; ++ pinctrl-3 = <&P9_29_gpio_pd_pin>; ++ pinctrl-4 = <&P9_29_pwm_pin>; ++ pinctrl-5 = <&P9_29_spi_pin>; ++ pinctrl-6 = <&P9_29_pruout_pin>; ++ pinctrl-7 = <&P9_29_pruin_pin>; ++ }; ++ ++ P9_30_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin"; ++ pinctrl-0 = <&P9_30_default_pin>; ++ pinctrl-1 = <&P9_30_gpio_pin>; ++ pinctrl-2 = <&P9_30_gpio_pu_pin>; ++ pinctrl-3 = <&P9_30_gpio_pd_pin>; ++ pinctrl-4 = <&P9_30_pwm_pin>; ++ pinctrl-5 = <&P9_30_spi_pin>; ++ pinctrl-6 = <&P9_30_pruout_pin>; ++ pinctrl-7 = <&P9_30_pruin_pin>; ++ }; ++ ++ P9_31_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin"; ++ pinctrl-0 = <&P9_31_default_pin>; ++ pinctrl-1 = <&P9_31_gpio_pin>; ++ pinctrl-2 = <&P9_31_gpio_pu_pin>; ++ pinctrl-3 = <&P9_31_gpio_pd_pin>; ++ pinctrl-4 = <&P9_31_pwm_pin>; ++ pinctrl-5 = <&P9_31_spi_pin>; ++ pinctrl-6 = <&P9_31_pruout_pin>; ++ pinctrl-7 = <&P9_31_pruin_pin>; ++ }; ++ ++ P9_41_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer", "pruin"; ++ pinctrl-0 = <&P9_41_default_pin>; ++ pinctrl-1 = <&P9_41_gpio_pin>; ++ pinctrl-2 = <&P9_41_gpio_pu_pin>; ++ pinctrl-3 = <&P9_41_gpio_pd_pin>; ++ pinctrl-4 = <&P9_41_timer_pin>; ++ pinctrl-5 = <&P9_41_pruin_pin>; ++ }; ++ ++ P9_91_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_91_default_pin>; ++ pinctrl-1 = <&P9_91_gpio_pin>; ++ pinctrl-2 = <&P9_91_gpio_pu_pin>; ++ pinctrl-3 = <&P9_91_gpio_pd_pin>; ++ pinctrl-4 = <&P9_91_qep_pin>; ++ pinctrl-5 = <&P9_91_pruout_pin>; ++ pinctrl-6 = <&P9_91_pruin_pin>; ++ }; ++ ++ P9_42_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "uart", "spics", "spiclk"; ++ pinctrl-0 = <&P9_42_default_pin>; ++ pinctrl-1 = <&P9_42_gpio_pin>; ++ pinctrl-2 = <&P9_42_gpio_pu_pin>; ++ pinctrl-3 = <&P9_42_gpio_pd_pin>; ++ pinctrl-4 = <&P9_42_pwm_pin>; ++ pinctrl-5 = <&P9_42_uart_pin>; ++ pinctrl-6 = <&P9_42_spics_pin>; ++ pinctrl-7 = <&P9_42_spiclk_pin>; ++ }; ++ ++ P9_92_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_92_default_pin>; ++ pinctrl-1 = <&P9_92_gpio_pin>; ++ pinctrl-2 = <&P9_92_gpio_pu_pin>; ++ pinctrl-3 = <&P9_92_gpio_pd_pin>; ++ pinctrl-4 = <&P9_92_qep_pin>; ++ pinctrl-5 = <&P9_92_pruout_pin>; ++ pinctrl-6 = <&P9_92_pruin_pin>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ // !!!WARNING!!! ++ // gpio-of-helper &gpio pointers are off-by-one vs. the hardware: ++ // hardware GPIO bank 0 = &gpio1 ++ cape-universal { ++ compatible = "gpio-of-helper"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ P8_07 { ++ gpio-name = "P8_07"; ++ gpio = <&gpio3 2 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_08 { ++ gpio-name = "P8_08"; ++ gpio = <&gpio3 3 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_09 { ++ gpio-name = "P8_09"; ++ gpio = <&gpio3 5 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_10 { ++ gpio-name = "P8_10"; ++ gpio = <&gpio3 4 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_11 { ++ gpio-name = "P8_11"; ++ gpio = <&gpio2 13 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_12 { ++ gpio-name = "P8_12"; ++ gpio = <&gpio2 12 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_13 { ++ gpio-name = "P8_13"; ++ gpio = <&gpio1 23 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_14 { ++ gpio-name = "P8_14"; ++ gpio = <&gpio1 26 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_15 { ++ gpio-name = "P8_15"; ++ gpio = <&gpio2 15 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_16 { ++ gpio-name = "P8_16"; ++ gpio = <&gpio2 14 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_17 { ++ gpio-name = "P8_17"; ++ gpio = <&gpio1 27 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_18 { ++ gpio-name = "P8_18"; ++ gpio = <&gpio3 1 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_19 { ++ gpio-name = "P8_19"; ++ gpio = <&gpio1 22 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_26 { ++ gpio-name = "P8_26"; ++ gpio = <&gpio2 29 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ ++ P9_11 { ++ gpio-name = "P9_11"; ++ gpio = <&gpio1 30 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_12 { ++ gpio-name = "P9_12"; ++ gpio = <&gpio2 28 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_13 { ++ gpio-name = "P9_13"; ++ gpio = <&gpio1 31 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_14 { ++ gpio-name = "P9_14"; ++ gpio = <&gpio2 18 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_15 { ++ gpio-name = "P9_15"; ++ gpio = <&gpio2 16 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_16 { ++ gpio-name = "P9_16"; ++ gpio = <&gpio2 19 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_17 { ++ gpio-name = "P9_17"; ++ gpio = <&gpio1 5 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_18 { ++ gpio-name = "P9_18"; ++ gpio = <&gpio1 4 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ // I2C pins ++ // P9_19 ++ // P9_20 ++ ++ P9_21 { ++ gpio-name = "P9_21"; ++ gpio = <&gpio1 3 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_22 { ++ gpio-name = "P9_22"; ++ gpio = <&gpio1 2 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_23 { ++ gpio-name = "P9_23"; ++ gpio = <&gpio2 17 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_24 { ++ gpio-name = "P9_24"; ++ gpio = <&gpio1 15 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_25 { ++ gpio-name = "P9_25"; ++ gpio = <&gpio4 21 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_26 { ++ gpio-name = "P9_26"; ++ gpio = <&gpio1 14 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_27 { ++ gpio-name = "P9_27"; ++ gpio = <&gpio4 19 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_28 { ++ gpio-name = "P9_28"; ++ gpio = <&gpio4 17 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_29 { ++ gpio-name = "P9_29"; ++ gpio = <&gpio4 15 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_30 { ++ gpio-name = "P9_30"; ++ gpio = <&gpio4 16 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_31 { ++ gpio-name = "P9_31"; ++ gpio = <&gpio4 14 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_41 { ++ gpio-name = "P9_41"; ++ gpio = <&gpio1 20 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_91 { ++ gpio-name = "P9_91"; ++ gpio = <&gpio4 20 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_42 { ++ gpio-name = "P9_42"; ++ gpio = <&gpio1 7 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_92 { ++ gpio-name = "P9_92"; ++ gpio = <&gpio4 18 0>; ++ input; ++ dir-changeable; ++ }; ++ }; ++ }; ++ }; ++ ++ ++ ++ /************************/ ++ /* UARTs */ ++ /************************/ ++ ++ fragment@10 { ++ target = <&uart2>; /* really uart1 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@11 { ++ target = <&uart3>; /* really uart2 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@12 { ++ target = <&uart5>; /* really uart4 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++// /* UART 5 only available on LCD/HDMI pins */ ++// fragment@13 { ++// target = <&uart6>; /* really uart5 */ ++// __overlay__ { ++// status = "okay"; ++// pinctrl-names = "default"; ++// pinctrl-0 = <>; ++// }; ++// }; ++ ++ /************************/ ++ /* Timers / PWM */ ++ /************************/ ++ ++ fragment@20 { ++ target = <&epwmss0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@21 { ++ target = <&ehrpwm0>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@22 { ++ target = <&ecap0>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@23 { ++ target = <&epwmss1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@24 { ++ target = <&ehrpwm1>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@25 { ++ target = <&epwmss2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@26 { ++ target = <&ehrpwm2>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@27 { ++ target = <&ecap2>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ /************************/ ++ /* I2C / SPI */ ++ /************************/ ++ ++ ++ fragment@30 { ++ target = <&i2c1>; /* i2c1 is numbered correctly */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ /* this is the configuration part */ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* add any i2c devices on the bus here */ ++ ++ // commented out example of a touchscreen (taken from BB-BONE-LCD7-01-00A4) */ ++ // maxtouch@4a { ++ // compatible = "mXT224"; ++ // reg = <0x4a>; ++ // interrupt-parent = <&gpio4>; ++ // interrupts = <19 0x0>; ++ // atmel,irq-gpio = <&gpio4 19 0>; ++ // }; ++ }; ++ }; ++ ++ fragment@31 { ++ target = <&spi0>; /* spi0 is numbered correctly */ ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ spi0channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ ++ spi0channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++ }; ++ }; ++ ++ fragment@32 { ++ target = <&spi1>; /* spi1 is numbered correctly */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spi1channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ spi1channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++ }; ++ }; ++ ++ fragment@33 { ++ target = <&dcan0>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@34 { ++ target = <&dcan1>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ ++ /************************/ ++ /* PRUSS */ ++ /************************/ ++ ++ fragment@40 { ++ target = <&pruss>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++}; +diff --git a/firmware/capes/cape-universaln-00A0.dts b/firmware/capes/cape-universaln-00A0.dts +new file mode 100644 +index 0000000..a4bdbf0 +--- /dev/null ++++ b/firmware/capes/cape-universaln-00A0.dts +@@ -0,0 +1,1609 @@ ++// Copyright 2013 ++// Charles Steinkuehler ++// ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; either version 2 of the License, or ++// (at your option) any later version. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License ++// along with this program; if not, write to the Free Software ++// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "cape-bone-universal"; ++ version = "00A0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ ++/* "P8.1", GND */ ++/* "P8.2", GND */ ++/* "P8.3", emmc */ ++/* "P8.4", emmc */ ++/* "P8.5", emmc */ ++/* "P8.6", emmc */ ++ "P8.7", ++ "P8.8", ++ "P8.9", ++ "P8.10", ++ "P8.11", ++ "P8.12", ++ "P8.13", ++ "P8.14", ++ "P8.15", ++ "P8.16", ++ "P8.17", ++ "P8.18", ++ "P8.19", ++/* "P8.20", emmc */ ++/* "P8.21", emmc */ ++/* "P8.22", emmc */ ++/* "P8.23", emmc */ ++/* "P8.24", emmc */ ++/* "P8.25", emmc */ ++ "P8.26", ++/* "P8.27", hdmi */ ++/* "P8.28", hdmi */ ++/* "P8.29", hdmi */ ++/* "P8.30", hdmi */ ++/* "P8.31", hdmi */ ++/* "P8.32", hdmi */ ++/* "P8.33", hdmi */ ++/* "P8.34", hdmi */ ++/* "P8.35", hdmi */ ++/* "P8.36", hdmi */ ++/* "P8.37", hdmi */ ++/* "P8.38", hdmi */ ++/* "P8.39", hdmi */ ++/* "P8.40", hdmi */ ++/* "P8.41", hdmi */ ++/* "P8.42", hdmi */ ++/* "P8.43", hdmi */ ++/* "P8.44", hdmi */ ++/* "P8.45", hdmi */ ++/* "P8.46", hdmi */ ++ ++/* "P9.1", GND */ ++/* "P9.2", GND */ ++/* "P9.3", 3.3V */ ++/* "P9.4", 3.3V */ ++/* "P9.5", VDD_5V */ ++/* "P9.6", VDD_5V */ ++/* "P9.7", SYS_5V */ ++/* "P9.8", SYS_5V */ ++/* "P9.9", PWR_BUT */ ++/* "P9.10", RESETn */ ++ "P9.11", ++ "P9.12", ++ "P9.13", ++ "P9.14", ++ "P9.15", ++ "P9.16", ++ "P9.17", ++ "P9.18", ++/* "P9.19", I2C */ ++/* "P9.20", I2C */ ++ "P9.21", ++ "P9.22", ++ "P9.23", ++ "P9.24", ++/* "P9.25", Audio */ ++ "P9.26", ++ "P9.27", ++/* "P9.28", Audio */ ++/* "P9.29", Audio */ ++ "P9.30", ++ "P9.31", ++/* "P9.32", VADC */ ++/* "P9.33", AIN4 */ ++/* "P9.34", AGND */ ++/* "P9.35", AIN6 */ ++/* "P9.36", AIN5 */ ++/* "P9.37", AIN2 */ ++/* "P9.38", AIN3 */ ++/* "P9.39", AIN0 */ ++/* "P9.40", AIN1 */ ++ "P9.41", ++ "P9.41.1", ++ "P9.42", ++ "P9.42.1", ++/* "P9.43", GND */ ++/* "P9.44", GND */ ++/* "P9.45", GND */ ++/* "P9.46", GND */ ++ ++ "uart1", ++ "uart2", ++ "uart4", ++// "uart5", /* Conflicts with HDMI */ ++ ++ "ehrpwm0A", ++ "ehrpwm0B", ++ "ehrpwm1A", ++ "ehrpwm1B", ++ "ehrpwm2A", ++ "ehrpwm2B", ++ ++// "epwmss0", ++// "ehrpwm0", ++// "ecap0", ++// "epwmss1", ++// "ehrpwm1", ++// "epwmss2", ++// "ehrpwm2", ++// "ecap2", ++ ++ "i2c1", ++ "spi1", ++ "spi0", ++ "dcan0", ++ "dcan1", ++ ++ "pru0", ++ "pru1", ++ "pruss"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ /* P8_01 GND */ ++ /* P8_02 GND */ ++ /* P8_03 (ZCZ ball R9 ) emmc */ ++ /* P8_04 (ZCZ ball T9 ) emmc */ ++ /* P8_05 (ZCZ ball R8 ) emmc */ ++ /* P8_06 (ZCZ ball T8 ) emmc */ ++ ++ /* P8_07 (ZCZ ball R7 ) */ ++ P8_07_default_pin: pinmux_P8_07_default_pin { ++ pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_07_gpio_pin: pinmux_P8_07_gpio_pin { ++ pinctrl-single,pins = <0x090 0x2F>; }; /* Mode 7, RxActive */ ++ P8_07_gpio_pu_pin: pinmux_P8_07_gpio_pu_pin { ++ pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_07_gpio_pd_pin: pinmux_P8_07_gpio_pd_pin { ++ pinctrl-single,pins = <0x090 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_07_timer_pin: pinmux_P8_07_timer_pin { ++ pinctrl-single,pins = <0x090 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ ++ /* P8_08 (ZCZ ball T7 ) */ ++ P8_08_default_pin: pinmux_P8_08_default_pin { ++ pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_08_gpio_pin: pinmux_P8_08_gpio_pin { ++ pinctrl-single,pins = <0x094 0x2F>; }; /* Mode 7, RxActive */ ++ P8_08_gpio_pu_pin: pinmux_P8_08_gpio_pu_pin { ++ pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_08_gpio_pd_pin: pinmux_P8_08_gpio_pd_pin { ++ pinctrl-single,pins = <0x094 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_08_timer_pin: pinmux_P8_08_timer_pin { ++ pinctrl-single,pins = <0x094 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ ++ /* P8_09 (ZCZ ball T6 ) */ ++ P8_09_default_pin: pinmux_P8_09_default_pin { ++ pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_09_gpio_pin: pinmux_P8_09_gpio_pin { ++ pinctrl-single,pins = <0x09c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_09_gpio_pu_pin: pinmux_P8_09_gpio_pu_pin { ++ pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_09_gpio_pd_pin: pinmux_P8_09_gpio_pd_pin { ++ pinctrl-single,pins = <0x09c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_09_timer_pin: pinmux_P8_09_timer_pin { ++ pinctrl-single,pins = <0x09c 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ ++ /* P8_10 (ZCZ ball U6 ) */ ++ P8_10_default_pin: pinmux_P8_10_default_pin { ++ pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_10_gpio_pin: pinmux_P8_10_gpio_pin { ++ pinctrl-single,pins = <0x098 0x2F>; }; /* Mode 7, RxActive */ ++ P8_10_gpio_pu_pin: pinmux_P8_10_gpio_pu_pin { ++ pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_10_gpio_pd_pin: pinmux_P8_10_gpio_pd_pin { ++ pinctrl-single,pins = <0x098 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_10_timer_pin: pinmux_P8_10_timer_pin { ++ pinctrl-single,pins = <0x098 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ ++ /* P8_11 (ZCZ ball R12) */ ++ P8_11_default_pin: pinmux_P8_11_default_pin { ++ pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_11_gpio_pin: pinmux_P8_11_gpio_pin { ++ pinctrl-single,pins = <0x034 0x2F>; }; /* Mode 7, RxActive */ ++ P8_11_gpio_pu_pin: pinmux_P8_11_gpio_pu_pin { ++ pinctrl-single,pins = <0x034 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_11_gpio_pd_pin: pinmux_P8_11_gpio_pd_pin { ++ pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_11_pruout_pin: pinmux_P8_11_pruout_pin { ++ pinctrl-single,pins = <0x034 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ P8_11_qep_pin: pinmux_P8_11_qep_pin { ++ pinctrl-single,pins = <0x034 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_12 (ZCZ ball T12) */ ++ P8_12_default_pin: pinmux_P8_12_default_pin { ++ pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_12_gpio_pin: pinmux_P8_12_gpio_pin { ++ pinctrl-single,pins = <0x030 0x2F>; }; /* Mode 7, RxActive */ ++ P8_12_gpio_pu_pin: pinmux_P8_12_gpio_pu_pin { ++ pinctrl-single,pins = <0x030 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_12_gpio_pd_pin: pinmux_P8_12_gpio_pd_pin { ++ pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_12_pruout_pin: pinmux_P8_12_pruout_pin { ++ pinctrl-single,pins = <0x030 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ P8_12_qep_pin: pinmux_P8_12_qep_pin { ++ pinctrl-single,pins = <0x030 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_13 (ZCZ ball T10) */ ++ P8_13_default_pin: pinmux_P8_13_default_pin { ++ pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_13_gpio_pin: pinmux_P8_13_gpio_pin { ++ pinctrl-single,pins = <0x024 0x2F>; }; /* Mode 7, RxActive */ ++ P8_13_gpio_pu_pin: pinmux_P8_13_gpio_pu_pin { ++ pinctrl-single,pins = <0x024 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_13_gpio_pd_pin: pinmux_P8_13_gpio_pd_pin { ++ pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_13_pwm_pin: pinmux_P8_13_pwm_pin { ++ pinctrl-single,pins = <0x024 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_14 (ZCZ ball T11) */ ++ P8_14_default_pin: pinmux_P8_14_default_pin { ++ pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_14_gpio_pin: pinmux_P8_14_gpio_pin { ++ pinctrl-single,pins = <0x028 0x2F>; }; /* Mode 7, RxActive */ ++ P8_14_gpio_pu_pin: pinmux_P8_14_gpio_pu_pin { ++ pinctrl-single,pins = <0x028 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_14_gpio_pd_pin: pinmux_P8_14_gpio_pd_pin { ++ pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_14_pwm_pin: pinmux_P8_14_pwm_pin { ++ pinctrl-single,pins = <0x028 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_15 (ZCZ ball U13) */ ++ P8_15_default_pin: pinmux_P8_15_default_pin { ++ pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_15_gpio_pin: pinmux_P8_15_gpio_pin { ++ pinctrl-single,pins = <0x03c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_15_gpio_pu_pin: pinmux_P8_15_gpio_pu_pin { ++ pinctrl-single,pins = <0x03c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_15_gpio_pd_pin: pinmux_P8_15_gpio_pd_pin { ++ pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_15_pruin_pin: pinmux_P8_15_pruin_pin { ++ pinctrl-single,pins = <0x03c 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ P8_15_qep_pin: pinmux_P8_15_qep_pin { ++ pinctrl-single,pins = <0x03c 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_16 (ZCZ ball V13) */ ++ P8_16_default_pin: pinmux_P8_16_default_pin { ++ pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_16_gpio_pin: pinmux_P8_16_gpio_pin { ++ pinctrl-single,pins = <0x038 0x2F>; }; /* Mode 7, RxActive */ ++ P8_16_gpio_pu_pin: pinmux_P8_16_gpio_pu_pin { ++ pinctrl-single,pins = <0x038 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_16_gpio_pd_pin: pinmux_P8_16_gpio_pd_pin { ++ pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_16_pruin_pin: pinmux_P8_16_pruin_pin { ++ pinctrl-single,pins = <0x038 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ P8_16_qep_pin: pinmux_P8_16_qep_pin { ++ pinctrl-single,pins = <0x038 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_17 (ZCZ ball U12) */ ++ P8_17_default_pin: pinmux_P8_17_default_pin { ++ pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_17_gpio_pin: pinmux_P8_17_gpio_pin { ++ pinctrl-single,pins = <0x02c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_17_gpio_pu_pin: pinmux_P8_17_gpio_pu_pin { ++ pinctrl-single,pins = <0x02c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_17_gpio_pd_pin: pinmux_P8_17_gpio_pd_pin { ++ pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_17_pwm_pin: pinmux_P8_17_pwm_pin { ++ pinctrl-single,pins = <0x02c 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_18 (ZCZ ball V12) */ ++ P8_18_default_pin: pinmux_P8_18_default_pin { ++ pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_18_gpio_pin: pinmux_P8_18_gpio_pin { ++ pinctrl-single,pins = <0x08c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_18_gpio_pu_pin: pinmux_P8_18_gpio_pu_pin { ++ pinctrl-single,pins = <0x08c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_18_gpio_pd_pin: pinmux_P8_18_gpio_pd_pin { ++ pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_19 (ZCZ ball U10) */ ++ P8_19_default_pin: pinmux_P8_19_default_pin { ++ pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_19_gpio_pin: pinmux_P8_19_gpio_pin { ++ pinctrl-single,pins = <0x020 0x2F>; }; /* Mode 7, RxActive */ ++ P8_19_gpio_pu_pin: pinmux_P8_19_gpio_pu_pin { ++ pinctrl-single,pins = <0x020 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_19_gpio_pd_pin: pinmux_P8_19_gpio_pd_pin { ++ pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P8_19_pwm_pin: pinmux_P8_19_pwm_pin { ++ pinctrl-single,pins = <0x020 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P8_20 (ZCZ ball V9 ) emmc */ ++ /* P8_21 (ZCZ ball U9 ) emmc */ ++ /* P8_22 (ZCZ ball V8 ) emmc */ ++ /* P8_23 (ZCZ ball U8 ) emmc */ ++ /* P8_24 (ZCZ ball V7 ) emmc */ ++ /* P8_25 (ZCZ ball U7 ) emmc */ ++ ++ /* P8_26 (ZCZ ball V6 ) */ ++ P8_26_default_pin: pinmux_P8_26_default_pin { ++ pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_26_gpio_pin: pinmux_P8_26_gpio_pin { ++ pinctrl-single,pins = <0x07c 0x2F>; }; /* Mode 7, RxActive */ ++ P8_26_gpio_pu_pin: pinmux_P8_26_gpio_pu_pin { ++ pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P8_26_gpio_pd_pin: pinmux_P8_26_gpio_pd_pin { ++ pinctrl-single,pins = <0x07c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P8_27 (ZCZ ball U5 ) hdmi */ ++ /* P8_28 (ZCZ ball V5 ) hdmi */ ++ /* P8_29 (ZCZ ball R5 ) hdmi */ ++ /* P8_30 (ZCZ ball R6 ) hdmi */ ++ /* P8_31 (ZCZ ball V4 ) hdmi */ ++ /* P8_32 (ZCZ ball T5 ) hdmi */ ++ /* P8_33 (ZCZ ball V3 ) hdmi */ ++ /* P8_34 (ZCZ ball U4 ) hdmi */ ++ /* P8_35 (ZCZ ball V2 ) hdmi */ ++ /* P8_36 (ZCZ ball U3 ) hdmi */ ++ /* P8_37 (ZCZ ball U1 ) hdmi */ ++ /* P8_38 (ZCZ ball U2 ) hdmi */ ++ /* P8_39 (ZCZ ball T3 ) hdmi */ ++ /* P8_40 (ZCZ ball T4 ) hdmi */ ++ /* P8_41 (ZCZ ball T1 ) hdmi */ ++ /* P8_42 (ZCZ ball T2 ) hdmi */ ++ /* P8_43 (ZCZ ball R3 ) hdmi */ ++ /* P8_44 (ZCZ ball R4 ) hdmi */ ++ /* P8_45 (ZCZ ball R1 ) hdmi */ ++ /* P8_46 (ZCZ ball R2 ) hdmi */ ++ ++ ++ /************************/ ++ /* P9 Header */ ++ /************************/ ++ ++ /* P9_01 GND */ ++ /* P9_02 GND */ ++ /* P9_03 3.3V */ ++ /* P9_04 3.3V */ ++ /* P9_05 VDD_5V */ ++ /* P9_06 VDD_5V */ ++ /* P9_07 SYS_5V */ ++ /* P9_08 SYS_5V */ ++ /* P9_09 PWR_BUT */ ++ /* P9_10 (ZCZ ball A10) RESETn */ ++ ++ /* P9_11 (ZCZ ball T17) */ ++ P9_11_default_pin: pinmux_P9_11_default_pin { ++ pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_11_gpio_pin: pinmux_P9_11_gpio_pin { ++ pinctrl-single,pins = <0x070 0x2F>; }; /* Mode 7, RxActive */ ++ P9_11_gpio_pu_pin: pinmux_P9_11_gpio_pu_pin { ++ pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_11_gpio_pd_pin: pinmux_P9_11_gpio_pd_pin { ++ pinctrl-single,pins = <0x070 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_11_uart_pin: pinmux_P9_11_uart_pin { ++ pinctrl-single,pins = <0x070 0x36>; }; /* Mode 6, Pull-Up, RxActive */ ++ ++ /* P9_12 (ZCZ ball U18) */ ++ P9_12_default_pin: pinmux_P9_12_default_pin { ++ pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_12_gpio_pin: pinmux_P9_12_gpio_pin { ++ pinctrl-single,pins = <0x078 0x2F>; }; /* Mode 7, RxActive */ ++ P9_12_gpio_pu_pin: pinmux_P9_12_gpio_pu_pin { ++ pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_12_gpio_pd_pin: pinmux_P9_12_gpio_pd_pin { ++ pinctrl-single,pins = <0x078 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ ++ /* P9_13 (ZCZ ball U17) */ ++ P9_13_default_pin: pinmux_P9_13_default_pin { ++ pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_13_gpio_pin: pinmux_P9_13_gpio_pin { ++ pinctrl-single,pins = <0x074 0x2F>; }; /* Mode 7, RxActive */ ++ P9_13_gpio_pu_pin: pinmux_P9_13_gpio_pu_pin { ++ pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_13_gpio_pd_pin: pinmux_P9_13_gpio_pd_pin { ++ pinctrl-single,pins = <0x074 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_13_uart_pin: pinmux_P9_13_uart_pin { ++ pinctrl-single,pins = <0x074 0x36>; }; /* Mode 6, Pull-Up, RxActive */ ++ ++ /* P9_14 (ZCZ ball U14) */ ++ P9_14_default_pin: pinmux_P9_14_default_pin { ++ pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_14_gpio_pin: pinmux_P9_14_gpio_pin { ++ pinctrl-single,pins = <0x048 0x2F>; }; /* Mode 7, RxActive */ ++ P9_14_gpio_pu_pin: pinmux_P9_14_gpio_pu_pin { ++ pinctrl-single,pins = <0x048 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_14_gpio_pd_pin: pinmux_P9_14_gpio_pd_pin { ++ pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_14_pwm_pin: pinmux_P9_14_pwm_pin { ++ pinctrl-single,pins = <0x048 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_15 (ZCZ ball R13) */ ++ P9_15_default_pin: pinmux_P9_15_default_pin { ++ pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_15_gpio_pin: pinmux_P9_15_gpio_pin { ++ pinctrl-single,pins = <0x040 0x2F>; }; /* Mode 7, RxActive */ ++ P9_15_gpio_pu_pin: pinmux_P9_15_gpio_pu_pin { ++ pinctrl-single,pins = <0x040 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_15_gpio_pd_pin: pinmux_P9_15_gpio_pd_pin { ++ pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_15_pwm_pin: pinmux_P9_15_pwm_pin { ++ pinctrl-single,pins = <0x040 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_16 (ZCZ ball T14) */ ++ P9_16_default_pin: pinmux_P9_16_default_pin { ++ pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_16_gpio_pin: pinmux_P9_16_gpio_pin { ++ pinctrl-single,pins = <0x04c 0x2F>; }; /* Mode 7, RxActive */ ++ P9_16_gpio_pu_pin: pinmux_P9_16_gpio_pu_pin { ++ pinctrl-single,pins = <0x04c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_16_gpio_pd_pin: pinmux_P9_16_gpio_pd_pin { ++ pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_16_pwm_pin: pinmux_P9_16_pwm_pin { ++ pinctrl-single,pins = <0x04c 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_17 (ZCZ ball A16) */ ++ P9_17_default_pin: pinmux_P9_17_default_pin { ++ pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_17_gpio_pin: pinmux_P9_17_gpio_pin { ++ pinctrl-single,pins = <0x15c 0x2F>; }; /* Mode 7, RxActive */ ++ P9_17_gpio_pu_pin: pinmux_P9_17_gpio_pu_pin { ++ pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_17_gpio_pd_pin: pinmux_P9_17_gpio_pd_pin { ++ pinctrl-single,pins = <0x15c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_17_spi_pin: pinmux_P9_17_spi_pin { ++ pinctrl-single,pins = <0x15c 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_17_i2c_pin: pinmux_P9_17_i2c_pin { ++ pinctrl-single,pins = <0x15c 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_17_pwm_pin: pinmux_P9_17_pwm_pin { ++ pinctrl-single,pins = <0x15c 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ ++ /* P9_18 (ZCZ ball B16) */ ++ P9_18_default_pin: pinmux_P9_18_default_pin { ++ pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_18_gpio_pin: pinmux_P9_18_gpio_pin { ++ pinctrl-single,pins = <0x158 0x2F>; }; /* Mode 7, RxActive */ ++ P9_18_gpio_pu_pin: pinmux_P9_18_gpio_pu_pin { ++ pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_18_gpio_pd_pin: pinmux_P9_18_gpio_pd_pin { ++ pinctrl-single,pins = <0x158 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_18_spi_pin: pinmux_P9_18_spi_pin { ++ pinctrl-single,pins = <0x158 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_18_i2c_pin: pinmux_P9_18_i2c_pin { ++ pinctrl-single,pins = <0x158 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_18_pwm_pin: pinmux_P9_18_pwm_pin { ++ pinctrl-single,pins = <0x158 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ ++ // Leave the cape I2C EEPROM bus alone ++ /* P9_19 (ZCZ ball D17) I2C */ ++ /* P9_20 (ZCZ ball D18) I2C */ ++ ++ /* P9_21 (ZCZ ball B17) */ ++ P9_21_default_pin: pinmux_P9_21_default_pin { ++ pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_21_gpio_pin: pinmux_P9_21_gpio_pin { ++ pinctrl-single,pins = <0x154 0x2F>; }; /* Mode 7, RxActive */ ++ P9_21_gpio_pu_pin: pinmux_P9_21_gpio_pu_pin { ++ pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_21_gpio_pd_pin: pinmux_P9_21_gpio_pd_pin { ++ pinctrl-single,pins = <0x154 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_21_spi_pin: pinmux_P9_21_spi_pin { ++ pinctrl-single,pins = <0x154 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_21_uart_pin: pinmux_P9_21_uart_pin { ++ pinctrl-single,pins = <0x154 0x31>; }; /* Mode 1, Pull-Up, RxActive */ ++ P9_21_i2c_pin: pinmux_P9_21_i2c_pin { ++ pinctrl-single,pins = <0x154 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_21_pwm_pin: pinmux_P9_21_pwm_pin { ++ pinctrl-single,pins = <0x154 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ ++ /* P9_22 (ZCZ ball A17) */ ++ P9_22_default_pin: pinmux_P9_22_default_pin { ++ pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_22_gpio_pin: pinmux_P9_22_gpio_pin { ++ pinctrl-single,pins = <0x150 0x2F>; }; /* Mode 7, RxActive */ ++ P9_22_gpio_pu_pin: pinmux_P9_22_gpio_pu_pin { ++ pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_22_gpio_pd_pin: pinmux_P9_22_gpio_pd_pin { ++ pinctrl-single,pins = <0x150 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_22_spi_pin: pinmux_P9_22_spi_pin { ++ pinctrl-single,pins = <0x150 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_22_uart_pin: pinmux_P9_22_uart_pin { ++ pinctrl-single,pins = <0x150 0x31>; }; /* Mode 1, Pull-Up, RxActive */ ++ P9_22_i2c_pin: pinmux_P9_22_i2c_pin { ++ pinctrl-single,pins = <0x150 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_22_pwm_pin: pinmux_P9_22_pwm_pin { ++ pinctrl-single,pins = <0x150 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ ++ /* P9_23 (ZCZ ball V14) */ ++ P9_23_default_pin: pinmux_P9_23_default_pin { ++ pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_23_gpio_pin: pinmux_P9_23_gpio_pin { ++ pinctrl-single,pins = <0x044 0x2F>; }; /* Mode 7, RxActive */ ++ P9_23_gpio_pu_pin: pinmux_P9_23_gpio_pu_pin { ++ pinctrl-single,pins = <0x044 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_23_gpio_pd_pin: pinmux_P9_23_gpio_pd_pin { ++ pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_23_pwm_pin: pinmux_P9_23_pwm_pin { ++ pinctrl-single,pins = <0x044 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_24 (ZCZ ball D15) */ ++ P9_24_default_pin: pinmux_P9_24_default_pin { ++ pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_24_gpio_pin: pinmux_P9_24_gpio_pin { ++ pinctrl-single,pins = <0x184 0x2F>; }; /* Mode 7, RxActive */ ++ P9_24_gpio_pu_pin: pinmux_P9_24_gpio_pu_pin { ++ pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_24_gpio_pd_pin: pinmux_P9_24_gpio_pd_pin { ++ pinctrl-single,pins = <0x184 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_24_uart_pin: pinmux_P9_24_uart_pin { ++ pinctrl-single,pins = <0x184 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_24_can_pin: pinmux_P9_24_can_pin { ++ pinctrl-single,pins = <0x184 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_24_i2c_pin: pinmux_P9_24_i2c_pin { ++ pinctrl-single,pins = <0x184 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ P9_24_pruin_pin: pinmux_P9_24_pruin_pin { ++ pinctrl-single,pins = <0x184 0x36>; }; /* Mode 6, Pull-Up, RxActive */ ++ ++ /* P9_25 (ZCZ ball A14) Audio */ ++ ++ /* P9_26 (ZCZ ball D16) */ ++ P9_26_default_pin: pinmux_P9_26_default_pin { ++ pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_26_gpio_pin: pinmux_P9_26_gpio_pin { ++ pinctrl-single,pins = <0x180 0x2F>; }; /* Mode 7, RxActive */ ++ P9_26_gpio_pu_pin: pinmux_P9_26_gpio_pu_pin { ++ pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_26_gpio_pd_pin: pinmux_P9_26_gpio_pd_pin { ++ pinctrl-single,pins = <0x180 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_26_uart_pin: pinmux_P9_26_uart_pin { ++ pinctrl-single,pins = <0x180 0x30>; }; /* Mode 0, Pull-Up, RxActive */ ++ P9_26_can_pin: pinmux_P9_26_can_pin { ++ pinctrl-single,pins = <0x180 0x32>; }; /* Mode 2, Pull-Up, RxActive */ ++ P9_26_i2c_pin: pinmux_P9_26_i2c_pin { ++ pinctrl-single,pins = <0x180 0x33>; }; /* Mode 3, Pull-Up, RxActive */ ++ P9_26_pruin_pin: pinmux_P9_26_pruin_pin { ++ pinctrl-single,pins = <0x180 0x36>; }; /* Mode 6, Pull-Up, RxActive */ ++ ++ /* P9_27 (ZCZ ball C13) */ ++ P9_27_default_pin: pinmux_P9_27_default_pin { ++ pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_27_gpio_pin: pinmux_P9_27_gpio_pin { ++ pinctrl-single,pins = <0x1a4 0x2F>; }; /* Mode 7, RxActive */ ++ P9_27_gpio_pu_pin: pinmux_P9_27_gpio_pu_pin { ++ pinctrl-single,pins = <0x1a4 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_27_gpio_pd_pin: pinmux_P9_27_gpio_pd_pin { ++ pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_27_qep_pin: pinmux_P9_27_qep_pin { ++ pinctrl-single,pins = <0x1a4 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_27_pruout_pin: pinmux_P9_27_pruout_pin { ++ pinctrl-single,pins = <0x1a4 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_27_pruin_pin: pinmux_P9_27_pruin_pin { ++ pinctrl-single,pins = <0x1a4 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_28 (ZCZ ball C12) Audio */ ++ /* P9_29 (ZCZ ball B13) Audio */ ++ ++ /* P9_30 (ZCZ ball D12) */ ++ P9_30_default_pin: pinmux_P9_30_default_pin { ++ pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_30_gpio_pin: pinmux_P9_30_gpio_pin { ++ pinctrl-single,pins = <0x198 0x2F>; }; /* Mode 7, RxActive */ ++ P9_30_gpio_pu_pin: pinmux_P9_30_gpio_pu_pin { ++ pinctrl-single,pins = <0x198 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_30_gpio_pd_pin: pinmux_P9_30_gpio_pd_pin { ++ pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_30_pwm_pin: pinmux_P9_30_pwm_pin { ++ pinctrl-single,pins = <0x198 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_30_spi_pin: pinmux_P9_30_spi_pin { ++ pinctrl-single,pins = <0x198 0x23>; }; /* Mode 3, Pull-Down, RxActive */ ++ P9_30_pruout_pin: pinmux_P9_30_pruout_pin { ++ pinctrl-single,pins = <0x198 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_30_pruin_pin: pinmux_P9_30_pruin_pin { ++ pinctrl-single,pins = <0x198 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_31 (ZCZ ball A13) Audio */ ++ ++ /* P9_32 VADC */ ++ /* P9_33 (ZCZ ball C8 ) AIN4 */ ++ /* P9_34 AGND */ ++ /* P9_35 (ZCZ ball A8 ) AIN6 */ ++ /* P9_36 (ZCZ ball B8 ) AIN5 */ ++ /* P9_37 (ZCZ ball B7 ) AIN2 */ ++ /* P9_38 (ZCZ ball A7 ) AIN3 */ ++ /* P9_39 (ZCZ ball B6 ) AIN0 */ ++ /* P9_40 (ZCZ ball C7 ) AIN1 */ ++ ++ /* P9_41 (ZCZ ball D14) */ ++ P9_41_default_pin: pinmux_P9_41_default_pin { ++ pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_41_gpio_pin: pinmux_P9_41_gpio_pin { ++ pinctrl-single,pins = <0x1b4 0x2F>; }; /* Mode 7, RxActive */ ++ P9_41_gpio_pu_pin: pinmux_P9_41_gpio_pu_pin { ++ pinctrl-single,pins = <0x1b4 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_41_gpio_pd_pin: pinmux_P9_41_gpio_pd_pin { ++ pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_41_timer_pin: pinmux_P9_41_timer_pin { ++ pinctrl-single,pins = <0x1b4 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ P9_41_pruin_pin: pinmux_P9_41_pruin_pin { ++ pinctrl-single,pins = <0x1b4 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ ++ /* P9_41.1 */ ++ /* P9_91 (ZCZ ball D13) */ ++ P9_91_default_pin: pinmux_P9_91_default_pin { ++ pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_91_gpio_pin: pinmux_P9_91_gpio_pin { ++ pinctrl-single,pins = <0x1a8 0x2F>; }; /* Mode 7, RxActive */ ++ P9_91_gpio_pu_pin: pinmux_P9_91_gpio_pu_pin { ++ pinctrl-single,pins = <0x1a8 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_91_gpio_pd_pin: pinmux_P9_91_gpio_pd_pin { ++ pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_91_qep_pin: pinmux_P9_91_qep_pin { ++ pinctrl-single,pins = <0x1a8 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_91_pruout_pin: pinmux_P9_91_pruout_pin { ++ pinctrl-single,pins = <0x1a8 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_91_pruin_pin: pinmux_P9_91_pruin_pin { ++ pinctrl-single,pins = <0x1a8 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_42 (ZCZ ball C18) */ ++ P9_42_default_pin: pinmux_P9_42_default_pin { ++ pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_42_gpio_pin: pinmux_P9_42_gpio_pin { ++ pinctrl-single,pins = <0x164 0x2F>; }; /* Mode 7, RxActive */ ++ P9_42_gpio_pu_pin: pinmux_P9_42_gpio_pu_pin { ++ pinctrl-single,pins = <0x164 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_42_gpio_pd_pin: pinmux_P9_42_gpio_pd_pin { ++ pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_42_pwm_pin: pinmux_P9_42_pwm_pin { ++ pinctrl-single,pins = <0x164 0x20>; }; /* Mode 0, Pull-Down, RxActive */ ++ P9_42_uart_pin: pinmux_P9_42_uart_pin { ++ pinctrl-single,pins = <0x164 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_42_spics_pin: pinmux_P9_42_spics_pin { ++ pinctrl-single,pins = <0x164 0x22>; }; /* Mode 2, Pull-Down, RxActive */ ++ P9_42_spiclk_pin: pinmux_P9_42_spiclk_pin { ++ pinctrl-single,pins = <0x164 0x24>; }; /* Mode 4, Pull-Down, RxActive */ ++ ++ /* P9_42.1 */ ++ /* P9_92 (ZCZ ball B12) */ ++ P9_92_default_pin: pinmux_P9_92_default_pin { ++ pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_92_gpio_pin: pinmux_P9_92_gpio_pin { ++ pinctrl-single,pins = <0x1a0 0x2F>; }; /* Mode 7, RxActive */ ++ P9_92_gpio_pu_pin: pinmux_P9_92_gpio_pu_pin { ++ pinctrl-single,pins = <0x1a0 0x37>; }; /* Mode 7, Pull-Up, RxActive */ ++ P9_92_gpio_pd_pin: pinmux_P9_92_gpio_pd_pin { ++ pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */ ++ P9_92_qep_pin: pinmux_P9_92_qep_pin { ++ pinctrl-single,pins = <0x1a0 0x21>; }; /* Mode 1, Pull-Down, RxActive */ ++ P9_92_pruout_pin: pinmux_P9_92_pruout_pin { ++ pinctrl-single,pins = <0x1a0 0x25>; }; /* Mode 5, Pull-Down, RxActive */ ++ P9_92_pruin_pin: pinmux_P9_92_pruin_pin { ++ pinctrl-single,pins = <0x1a0 0x26>; }; /* Mode 6, Pull-Down, RxActive */ ++ ++ /* P9_43 GND */ ++ /* P9_44 GND */ ++ /* P9_45 GND */ ++ /* P9_46 GND */ ++ ++ }; ++ }; ++ ++ ++ /************************/ ++ /* Pin Multiplexing */ ++ /************************/ ++ ++ fragment@1 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ P8_07_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_07_default_pin>; ++ pinctrl-1 = <&P8_07_gpio_pin>; ++ pinctrl-2 = <&P8_07_gpio_pu_pin>; ++ pinctrl-3 = <&P8_07_gpio_pd_pin>; ++ pinctrl-4 = <&P8_07_timer_pin>; ++ }; ++ ++ P8_08_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_08_default_pin>; ++ pinctrl-1 = <&P8_08_gpio_pin>; ++ pinctrl-2 = <&P8_08_gpio_pu_pin>; ++ pinctrl-3 = <&P8_08_gpio_pd_pin>; ++ pinctrl-4 = <&P8_08_timer_pin>; ++ }; ++ ++ P8_09_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_09_default_pin>; ++ pinctrl-1 = <&P8_09_gpio_pin>; ++ pinctrl-2 = <&P8_09_gpio_pu_pin>; ++ pinctrl-3 = <&P8_09_gpio_pd_pin>; ++ pinctrl-4 = <&P8_09_timer_pin>; ++ }; ++ ++ P8_10_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_10_default_pin>; ++ pinctrl-1 = <&P8_10_gpio_pin>; ++ pinctrl-2 = <&P8_10_gpio_pu_pin>; ++ pinctrl-3 = <&P8_10_gpio_pd_pin>; ++ pinctrl-4 = <&P8_10_timer_pin>; ++ }; ++ ++ P8_11_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "qep"; ++ pinctrl-0 = <&P8_11_default_pin>; ++ pinctrl-1 = <&P8_11_gpio_pin>; ++ pinctrl-2 = <&P8_11_gpio_pu_pin>; ++ pinctrl-3 = <&P8_11_gpio_pd_pin>; ++ pinctrl-4 = <&P8_11_pruout_pin>; ++ pinctrl-5 = <&P8_11_qep_pin>; ++ }; ++ ++ P8_12_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "qep"; ++ pinctrl-0 = <&P8_12_default_pin>; ++ pinctrl-1 = <&P8_12_gpio_pin>; ++ pinctrl-2 = <&P8_12_gpio_pu_pin>; ++ pinctrl-3 = <&P8_12_gpio_pd_pin>; ++ pinctrl-4 = <&P8_12_pruout_pin>; ++ pinctrl-5 = <&P8_12_qep_pin>; ++ }; ++ ++ P8_13_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_13_default_pin>; ++ pinctrl-1 = <&P8_13_gpio_pin>; ++ pinctrl-2 = <&P8_13_gpio_pu_pin>; ++ pinctrl-3 = <&P8_13_gpio_pd_pin>; ++ pinctrl-4 = <&P8_13_pwm_pin>; ++ }; ++ ++ P8_14_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_14_default_pin>; ++ pinctrl-1 = <&P8_14_gpio_pin>; ++ pinctrl-2 = <&P8_14_gpio_pu_pin>; ++ pinctrl-3 = <&P8_14_gpio_pd_pin>; ++ pinctrl-4 = <&P8_14_pwm_pin>; ++ }; ++ ++ P8_15_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin", "qep"; ++ pinctrl-0 = <&P8_15_default_pin>; ++ pinctrl-1 = <&P8_15_gpio_pin>; ++ pinctrl-2 = <&P8_15_gpio_pu_pin>; ++ pinctrl-3 = <&P8_15_gpio_pd_pin>; ++ pinctrl-4 = <&P8_15_pruin_pin>; ++ pinctrl-5 = <&P8_15_qep_pin>; ++ }; ++ ++ P8_16_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin", "qep"; ++ pinctrl-0 = <&P8_16_default_pin>; ++ pinctrl-1 = <&P8_16_gpio_pin>; ++ pinctrl-2 = <&P8_16_gpio_pu_pin>; ++ pinctrl-3 = <&P8_16_gpio_pd_pin>; ++ pinctrl-4 = <&P8_16_pruin_pin>; ++ pinctrl-5 = <&P8_16_qep_pin>; ++ }; ++ ++ P8_17_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_17_default_pin>; ++ pinctrl-1 = <&P8_17_gpio_pin>; ++ pinctrl-2 = <&P8_17_gpio_pu_pin>; ++ pinctrl-3 = <&P8_17_gpio_pd_pin>; ++ pinctrl-4 = <&P8_17_pwm_pin>; ++ }; ++ ++ P8_18_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio"; ++ pinctrl-0 = <&P8_18_default_pin>; ++ pinctrl-1 = <&P8_18_gpio_pin>; ++ pinctrl-2 = <&P8_18_gpio_pu_pin>; ++ pinctrl-3 = <&P8_18_gpio_pd_pin>; ++ }; ++ ++ P8_19_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_19_default_pin>; ++ pinctrl-1 = <&P8_19_gpio_pin>; ++ pinctrl-2 = <&P8_19_gpio_pu_pin>; ++ pinctrl-3 = <&P8_19_gpio_pd_pin>; ++ pinctrl-4 = <&P8_19_pwm_pin>; ++ }; ++ ++ P8_26_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio"; ++ pinctrl-0 = <&P8_26_default_pin>; ++ pinctrl-1 = <&P8_26_gpio_pin>; ++ pinctrl-2 = <&P8_26_gpio_pu_pin>; ++ pinctrl-3 = <&P8_26_gpio_pd_pin>; ++ }; ++ ++ ++ /************************/ ++ /* P9 Header */ ++ /************************/ ++ ++ P9_11_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; ++ pinctrl-0 = <&P9_11_default_pin>; ++ pinctrl-1 = <&P9_11_gpio_pin>; ++ pinctrl-2 = <&P9_11_gpio_pu_pin>; ++ pinctrl-3 = <&P9_11_gpio_pd_pin>; ++ pinctrl-4 = <&P9_11_uart_pin>; ++ }; ++ ++ P9_12_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio"; ++ pinctrl-0 = <&P9_12_default_pin>; ++ pinctrl-1 = <&P9_12_gpio_pin>; ++ pinctrl-2 = <&P9_12_gpio_pu_pin>; ++ pinctrl-3 = <&P9_12_gpio_pd_pin>; ++ }; ++ ++ P9_13_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; ++ pinctrl-0 = <&P9_13_default_pin>; ++ pinctrl-1 = <&P9_13_gpio_pin>; ++ pinctrl-2 = <&P9_13_gpio_pu_pin>; ++ pinctrl-3 = <&P9_13_gpio_pd_pin>; ++ pinctrl-4 = <&P9_13_uart_pin>; ++ }; ++ ++ P9_14_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_14_default_pin>; ++ pinctrl-1 = <&P9_14_gpio_pin>; ++ pinctrl-2 = <&P9_14_gpio_pu_pin>; ++ pinctrl-3 = <&P9_14_gpio_pd_pin>; ++ pinctrl-4 = <&P9_14_pwm_pin>; ++ }; ++ ++ P9_15_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_15_default_pin>; ++ pinctrl-1 = <&P9_15_gpio_pin>; ++ pinctrl-2 = <&P9_15_gpio_pu_pin>; ++ pinctrl-3 = <&P9_15_gpio_pd_pin>; ++ pinctrl-4 = <&P9_15_pwm_pin>; ++ }; ++ ++ P9_16_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_16_default_pin>; ++ pinctrl-1 = <&P9_16_gpio_pin>; ++ pinctrl-2 = <&P9_16_gpio_pu_pin>; ++ pinctrl-3 = <&P9_16_gpio_pd_pin>; ++ pinctrl-4 = <&P9_16_pwm_pin>; ++ }; ++ ++ P9_17_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm"; ++ pinctrl-0 = <&P9_17_default_pin>; ++ pinctrl-1 = <&P9_17_gpio_pin>; ++ pinctrl-2 = <&P9_17_gpio_pu_pin>; ++ pinctrl-3 = <&P9_17_gpio_pd_pin>; ++ pinctrl-4 = <&P9_17_spi_pin>; ++ pinctrl-5 = <&P9_17_i2c_pin>; ++ pinctrl-6 = <&P9_17_pwm_pin>; ++ }; ++ ++ P9_18_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm"; ++ pinctrl-0 = <&P9_18_default_pin>; ++ pinctrl-1 = <&P9_18_gpio_pin>; ++ pinctrl-2 = <&P9_18_gpio_pu_pin>; ++ pinctrl-3 = <&P9_18_gpio_pd_pin>; ++ pinctrl-4 = <&P9_18_spi_pin>; ++ pinctrl-5 = <&P9_18_i2c_pin>; ++ pinctrl-6 = <&P9_18_pwm_pin>; ++ }; ++ ++ // I2C Pins ++ // P9_19_pinmux ++ // P9_20_pinmux ++ ++ P9_21_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm"; ++ pinctrl-0 = <&P9_21_default_pin>; ++ pinctrl-1 = <&P9_21_gpio_pin>; ++ pinctrl-2 = <&P9_21_gpio_pu_pin>; ++ pinctrl-3 = <&P9_21_gpio_pd_pin>; ++ pinctrl-4 = <&P9_21_spi_pin>; ++ pinctrl-5 = <&P9_21_uart_pin>; ++ pinctrl-6 = <&P9_21_i2c_pin>; ++ pinctrl-7 = <&P9_21_pwm_pin>; ++ }; ++ ++ P9_22_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm"; ++ pinctrl-0 = <&P9_22_default_pin>; ++ pinctrl-1 = <&P9_22_gpio_pin>; ++ pinctrl-2 = <&P9_22_gpio_pu_pin>; ++ pinctrl-3 = <&P9_22_gpio_pd_pin>; ++ pinctrl-4 = <&P9_22_spi_pin>; ++ pinctrl-5 = <&P9_22_uart_pin>; ++ pinctrl-6 = <&P9_22_i2c_pin>; ++ pinctrl-7 = <&P9_22_pwm_pin>; ++ }; ++ ++ P9_23_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_23_default_pin>; ++ pinctrl-1 = <&P9_23_gpio_pin>; ++ pinctrl-2 = <&P9_23_gpio_pu_pin>; ++ pinctrl-3 = <&P9_23_gpio_pd_pin>; ++ pinctrl-4 = <&P9_23_pwm_pin>; ++ }; ++ ++ P9_24_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin"; ++ pinctrl-0 = <&P9_24_default_pin>; ++ pinctrl-1 = <&P9_24_gpio_pin>; ++ pinctrl-2 = <&P9_24_gpio_pu_pin>; ++ pinctrl-3 = <&P9_24_gpio_pd_pin>; ++ pinctrl-4 = <&P9_24_uart_pin>; ++ pinctrl-5 = <&P9_24_can_pin>; ++ pinctrl-6 = <&P9_24_i2c_pin>; ++ pinctrl-7 = <&P9_24_pruin_pin>; ++ }; ++ ++ ++ // Audio pin ++ // P9_25_pinmux ++ ++ P9_26_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin"; ++ pinctrl-0 = <&P9_26_default_pin>; ++ pinctrl-1 = <&P9_26_gpio_pin>; ++ pinctrl-2 = <&P9_26_gpio_pu_pin>; ++ pinctrl-3 = <&P9_26_gpio_pd_pin>; ++ pinctrl-4 = <&P9_26_uart_pin>; ++ pinctrl-5 = <&P9_26_can_pin>; ++ pinctrl-6 = <&P9_26_i2c_pin>; ++ pinctrl-7 = <&P9_26_pruin_pin>; ++ }; ++ ++ P9_27_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_27_default_pin>; ++ pinctrl-1 = <&P9_27_gpio_pin>; ++ pinctrl-2 = <&P9_27_gpio_pu_pin>; ++ pinctrl-3 = <&P9_27_gpio_pd_pin>; ++ pinctrl-4 = <&P9_27_qep_pin>; ++ pinctrl-5 = <&P9_27_pruout_pin>; ++ pinctrl-6 = <&P9_27_pruin_pin>; ++ }; ++ ++ // Audio pins ++ // P9_28_pinmux ++ // P9_29_pinmux ++ ++ P9_30_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin"; ++ pinctrl-0 = <&P9_30_default_pin>; ++ pinctrl-1 = <&P9_30_gpio_pin>; ++ pinctrl-2 = <&P9_30_gpio_pu_pin>; ++ pinctrl-3 = <&P9_30_gpio_pd_pin>; ++ pinctrl-4 = <&P9_30_pwm_pin>; ++ pinctrl-5 = <&P9_30_spi_pin>; ++ pinctrl-6 = <&P9_30_pruout_pin>; ++ pinctrl-7 = <&P9_30_pruin_pin>; ++ }; ++ ++ // Audio pin ++ // P9_31_pinmux ++ ++ P9_41_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer", "pruin"; ++ pinctrl-0 = <&P9_41_default_pin>; ++ pinctrl-1 = <&P9_41_gpio_pin>; ++ pinctrl-2 = <&P9_41_gpio_pu_pin>; ++ pinctrl-3 = <&P9_41_gpio_pd_pin>; ++ pinctrl-4 = <&P9_41_timer_pin>; ++ pinctrl-5 = <&P9_41_pruin_pin>; ++ }; ++ ++ P9_91_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_91_default_pin>; ++ pinctrl-1 = <&P9_91_gpio_pin>; ++ pinctrl-2 = <&P9_91_gpio_pu_pin>; ++ pinctrl-3 = <&P9_91_gpio_pd_pin>; ++ pinctrl-4 = <&P9_91_qep_pin>; ++ pinctrl-5 = <&P9_91_pruout_pin>; ++ pinctrl-6 = <&P9_91_pruin_pin>; ++ }; ++ ++ P9_42_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "uart", "spics", "spiclk"; ++ pinctrl-0 = <&P9_42_default_pin>; ++ pinctrl-1 = <&P9_42_gpio_pin>; ++ pinctrl-2 = <&P9_42_gpio_pu_pin>; ++ pinctrl-3 = <&P9_42_gpio_pd_pin>; ++ pinctrl-4 = <&P9_42_pwm_pin>; ++ pinctrl-5 = <&P9_42_uart_pin>; ++ pinctrl-6 = <&P9_42_spics_pin>; ++ pinctrl-7 = <&P9_42_spiclk_pin>; ++ }; ++ ++ P9_92_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_92_default_pin>; ++ pinctrl-1 = <&P9_92_gpio_pin>; ++ pinctrl-2 = <&P9_92_gpio_pu_pin>; ++ pinctrl-3 = <&P9_92_gpio_pd_pin>; ++ pinctrl-4 = <&P9_92_qep_pin>; ++ pinctrl-5 = <&P9_92_pruout_pin>; ++ pinctrl-6 = <&P9_92_pruin_pin>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ // !!!WARNING!!! ++ // gpio-of-helper &gpio pointers are off-by-one vs. the hardware: ++ // hardware GPIO bank 0 = &gpio1 ++ cape-universal { ++ compatible = "gpio-of-helper"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ P8_07 { ++ gpio-name = "P8_07"; ++ gpio = <&gpio3 2 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_08 { ++ gpio-name = "P8_08"; ++ gpio = <&gpio3 3 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_09 { ++ gpio-name = "P8_09"; ++ gpio = <&gpio3 5 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_10 { ++ gpio-name = "P8_10"; ++ gpio = <&gpio3 4 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_11 { ++ gpio-name = "P8_11"; ++ gpio = <&gpio2 13 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_12 { ++ gpio-name = "P8_12"; ++ gpio = <&gpio2 12 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_13 { ++ gpio-name = "P8_13"; ++ gpio = <&gpio1 23 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_14 { ++ gpio-name = "P8_14"; ++ gpio = <&gpio1 26 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_15 { ++ gpio-name = "P8_15"; ++ gpio = <&gpio2 15 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_16 { ++ gpio-name = "P8_16"; ++ gpio = <&gpio2 14 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_17 { ++ gpio-name = "P8_17"; ++ gpio = <&gpio1 27 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_18 { ++ gpio-name = "P8_18"; ++ gpio = <&gpio3 1 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_19 { ++ gpio-name = "P8_19"; ++ gpio = <&gpio1 22 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_26 { ++ gpio-name = "P8_26"; ++ gpio = <&gpio2 29 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ ++ P9_11 { ++ gpio-name = "P9_11"; ++ gpio = <&gpio1 30 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_12 { ++ gpio-name = "P9_12"; ++ gpio = <&gpio2 28 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_13 { ++ gpio-name = "P9_13"; ++ gpio = <&gpio1 31 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_14 { ++ gpio-name = "P9_14"; ++ gpio = <&gpio2 18 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_15 { ++ gpio-name = "P9_15"; ++ gpio = <&gpio2 16 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_16 { ++ gpio-name = "P9_16"; ++ gpio = <&gpio2 19 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_17 { ++ gpio-name = "P9_17"; ++ gpio = <&gpio1 5 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_18 { ++ gpio-name = "P9_18"; ++ gpio = <&gpio1 4 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ // I2C pins ++ // P9_19 ++ // P9_20 ++ ++ P9_21 { ++ gpio-name = "P9_21"; ++ gpio = <&gpio1 3 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_22 { ++ gpio-name = "P9_22"; ++ gpio = <&gpio1 2 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_23 { ++ gpio-name = "P9_23"; ++ gpio = <&gpio2 17 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_24 { ++ gpio-name = "P9_24"; ++ gpio = <&gpio1 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ // Audio pin ++ // P9_25 ++ ++ P9_26 { ++ gpio-name = "P9_26"; ++ gpio = <&gpio1 14 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_27 { ++ gpio-name = "P9_27"; ++ gpio = <&gpio4 19 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ // Audio pins ++ // P9_28 ++ // P9_29 ++ ++ P9_30 { ++ gpio-name = "P9_30"; ++ gpio = <&gpio4 16 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ // Audio pin ++ // P9_31 ++ ++ P9_41 { ++ gpio-name = "P9_41"; ++ gpio = <&gpio1 20 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_91 { ++ gpio-name = "P9_91"; ++ gpio = <&gpio4 20 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_42 { ++ gpio-name = "P9_42"; ++ gpio = <&gpio1 7 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_92 { ++ gpio-name = "P9_92"; ++ gpio = <&gpio4 18 0>; ++ input; ++ dir-changeable; ++ }; ++ }; ++ }; ++ }; ++ ++ ++ ++ /************************/ ++ /* UARTs */ ++ /************************/ ++ ++ fragment@10 { ++ target = <&uart2>; /* really uart1 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@11 { ++ target = <&uart3>; /* really uart2 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@12 { ++ target = <&uart5>; /* really uart4 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++// /* UART 5 only available on LCD/HDMI pins */ ++// fragment@13 { ++// target = <&uart6>; /* really uart5 */ ++// __overlay__ { ++// status = "okay"; ++// pinctrl-names = "default"; ++// pinctrl-0 = <>; ++// }; ++// }; ++ ++ /************************/ ++ /* Timers / PWM */ ++ /************************/ ++ ++ fragment@20 { ++ target = <&epwmss0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@21 { ++ target = <&ehrpwm0>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@22 { ++ target = <&ecap0>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@23 { ++ target = <&epwmss1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@24 { ++ target = <&ehrpwm1>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@25 { ++ target = <&epwmss2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@26 { ++ target = <&ehrpwm2>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@27 { ++ target = <&ecap2>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ /************************/ ++ /* I2C / SPI */ ++ /************************/ ++ ++ ++ fragment@30 { ++ target = <&i2c1>; /* i2c1 is numbered correctly */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ /* this is the configuration part */ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* add any i2c devices on the bus here */ ++ ++ // commented out example of a touchscreen (taken from BB-BONE-LCD7-01-00A4) */ ++ // maxtouch@4a { ++ // compatible = "mXT224"; ++ // reg = <0x4a>; ++ // interrupt-parent = <&gpio4>; ++ // interrupts = <19 0x0>; ++ // atmel,irq-gpio = <&gpio4 19 0>; ++ // }; ++ }; ++ }; ++ ++ fragment@31 { ++ target = <&spi0>; /* spi0 is numbered correctly */ ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ spi0channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ ++ spi0channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++ }; ++ }; ++ ++ fragment@32 { ++ target = <&spi1>; /* spi1 is numbered correctly */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spi1channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ spi1channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++ }; ++ }; ++ ++ fragment@33 { ++ target = <&dcan0>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ fragment@34 { ++ target = <&dcan1>; ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ }; ++ }; ++ ++ ++ /************************/ ++ /* PRUSS */ ++ /************************/ ++ ++ fragment@40 { ++ target = <&pruss>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++}; +-- +1.9.0 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0026-remove-1-wire-gpio-in-weather-cape-rev-B.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0026-remove-1-wire-gpio-in-weather-cape-rev-B.patch new file mode 100644 index 00000000..a492909b --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0026-remove-1-wire-gpio-in-weather-cape-rev-B.patch @@ -0,0 +1,60 @@ +From 9d2e7fecf424e08abdbbb88f1ae0e07c708723e6 Mon Sep 17 00:00:00 2001 +From: Hieu Duong +Date: Thu, 3 Apr 2014 14:49:33 -0500 +Subject: [PATCH 26/26] remove 1-wire gpio in weather cape rev B + +Signed-off-by: Hieu Duong +--- + firmware/capes/cape-bone-weather-00B0.dts | 30 ------------------------------ + 1 file changed, 30 deletions(-) + +diff --git a/firmware/capes/cape-bone-weather-00B0.dts b/firmware/capes/cape-bone-weather-00B0.dts +index e399cf3..29c5b27 100644 +--- a/firmware/capes/cape-bone-weather-00B0.dts ++++ b/firmware/capes/cape-bone-weather-00B0.dts +@@ -15,24 +15,7 @@ + version = "00B0"; + + /* state the resources this cape uses */ +- exclusive-use = +- /* the pin header uses */ +- "P8.6", /* gpio1_3 */ +- /* the hardware IP uses */ +- "gpio1_3"; +- + fragment@0 { +- target = <&am33xx_pinmux>; +- __overlay__ { +- weather_cape_w1_pins: pinmux_weather_cape_w1_pins { +- pinctrl-single,pins = < +- 0x0c 0x37 /* gpmc_ad3.gpio1_3, OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE7 - w1-gpio */ +- >; +- }; +- }; +- }; +- +- fragment@1 { + target = <&i2c2>; + + __overlay__ { +@@ -60,17 +43,4 @@ + }; + }; + +- fragment@2 { +- target = <&ocp>; +- __overlay__ { +- onewire@0 { +- compatible = "w1-gpio"; +- pinctrl-names = "default"; +- pinctrl-0 = <&weather_cape_w1_pins>; +- status = "okay"; +- +- gpios = <&gpio2 3 0>; +- }; +- }; +- }; + }; +-- +1.9.1 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0027-cape-add-cape-bone-ibb-00A0.dts.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0027-cape-add-cape-bone-ibb-00A0.dts.patch new file mode 100644 index 00000000..4249f2fd --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0027-cape-add-cape-bone-ibb-00A0.dts.patch @@ -0,0 +1,164 @@ +From acde0fb4f7204780d78a78c3f561bbae30700894 Mon Sep 17 00:00:00 2001 +From: Robert Budde +Date: Mon, 7 Apr 2014 14:19:19 -0500 +Subject: [PATCH 27/27] cape: add cape-bone-ibb-00A0.dts + +Signed-off-by: Robert Budde +Signed-off-by: Robert Nelson +--- + firmware/Makefile | 3 +- + firmware/capes/cape-bone-ibb-00A0.dts | 128 ++++++++++++++++++++++++++++++++++ + 2 files changed, 130 insertions(+), 1 deletion(-) + create mode 100644 firmware/capes/cape-bone-ibb-00A0.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index 4e56720..a2b3218 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -200,7 +200,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + cape-bone-replicape-00A3.dtbo \ + cape-univ-emmc-00A0.dtbo \ + cape-universal-00A0.dtbo \ +- cape-universaln-00A0.dtbo ++ cape-universaln-00A0.dtbo \ ++ cape-bone-ibb-00A0.dtbo + + # the geiger cape + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \ +diff --git a/firmware/capes/cape-bone-ibb-00A0.dts b/firmware/capes/cape-bone-ibb-00A0.dts +new file mode 100644 +index 0000000..dfd7447 +--- /dev/null ++++ b/firmware/capes/cape-bone-ibb-00A0.dts +@@ -0,0 +1,128 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ part-number = "cape-bone-ibb"; ++ version = "00A0"; ++ exclusive-use = "P9.24", "P9.26", "uart1", ++ "P9.21", "P9.22", "uart2", ++ "P9.13", "P9.11", "uart4", ++ "P9.15"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ bb_uart1_pins: pinmux_bb_uart1_pins { ++ pinctrl-single,pins = <0x180 0x20 0x184 0x00>; ++ }; ++ bb_uart2_pins: pinmux_bb_uart2_pins { ++ pinctrl-single,pins = <0x150 0x21 0x154 0x01>; ++ }; ++ bb_uart4_pins: pinmux_bb_uart4_pins { ++ pinctrl-single,pins = <0x70 0x26 0x74 0x06>; ++ }; ++ rtc_int_pin: pinmux_rtc_int_pin { ++ pinctrl-single,pins = <0x40 0x37>; /* GPIO1_16 gpmc_a0 */ ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart2>; /* really uart1 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_uart1_pins>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&uart3>; /* really uart2 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_uart2_pins>; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&uart5>; /* really uart4 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_uart4_pins>; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c2>; ++ __overlay__ { ++ /* shut up DTC warnings */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* DS1307 RTC module */ ++ rtc@68 { ++ compatible = "dallas,ds3231"; ++ reg = <0x68>; ++ }; ++ ++ /* PCA9546 I2C multiplexer */ ++ i2cmux@70 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "nxp,pca9545"; ++ reg = <0x70>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "nxp,pca954x-bus"; ++ reg = <0>; ++ deselect_on_exit; ++ }; ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "nxp,pca954x-bus"; ++ reg = <1>; ++ deselect_on_exit; ++ }; ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "nxp,pca954x-bus"; ++ reg = <2>; ++ deselect_on_exit; ++ }; ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "nxp,pca954x-bus"; ++ reg = <3>; ++ deselect_on_exit; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&ocp>; ++ __overlay__ { ++ gpio_keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rtc_int_pin>; ++ int_x1 { ++ label = "RTC-INT"; ++ debounce_interval = <50>; ++ linux,code = <1>; ++ gpios = <&gpio2 16 0x5>; ++ gpio-key,wakeup; ++ }; ++ }; ++ }; ++ }; ++ ++}; +-- +1.9.1 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0028-adds-DTS-for-CryptoCape.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0028-adds-DTS-for-CryptoCape.patch new file mode 100644 index 00000000..07378c06 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0028-adds-DTS-for-CryptoCape.patch @@ -0,0 +1,150 @@ +From 345631012c9e401d787f823c8a0c4ee0d52a5faa Mon Sep 17 00:00:00 2001 +From: Josh Datko +Date: Wed, 2 Apr 2014 20:35:11 +0000 +Subject: [PATCH 28/28] adds DTS for CryptoCape + +Signed-off-by: Josh Datko +Signed-off-by: Robert Nelson +--- + firmware/Makefile | 3 +- + firmware/capes/BB-BONE-CRYPTO-00A0.dts | 114 +++++++++++++++++++++++++++++++++ + 2 files changed, 116 insertions(+), 1 deletion(-) + create mode 100644 firmware/capes/BB-BONE-CRYPTO-00A0.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index a2b3218..299b3a5 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -201,7 +201,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + cape-univ-emmc-00A0.dtbo \ + cape-universal-00A0.dtbo \ + cape-universaln-00A0.dtbo \ +- cape-bone-ibb-00A0.dtbo ++ cape-bone-ibb-00A0.dtbo \ ++ BB-BONE-CRYPTO-00A0.dtbo + + # the geiger cape + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \ +diff --git a/firmware/capes/BB-BONE-CRYPTO-00A0.dts b/firmware/capes/BB-BONE-CRYPTO-00A0.dts +new file mode 100644 +index 0000000..2528ae9 +--- /dev/null ++++ b/firmware/capes/BB-BONE-CRYPTO-00A0.dts +@@ -0,0 +1,114 @@ ++/* ++ * Copyright (C) 2014 Cryptotronix ++ * ++ * Cape support for the CryptoCape ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-CRYPTO"; ++ version = "00A0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header uses */ ++ /* For Flashing the ATmega328p */ ++ "P9.13", /* uart4_txd */ ++ "P9.11", /* uart4_rxd */ ++ "P9.23", /* gpio1_17 */ ++ /* As the AUTHO Input from the AES132 */ ++ "P8.11", /* gpio1_13 */ ++ /* the hardware ip uses */ ++ "uart4", ++ "gpio1_13", ++ "gpio1_17"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ cryptocape_pins: pinmux_cryptocape_pins { ++ pinctrl-single,pins = < ++ 0x044 0x17 /* gpio1_17 FAST | OUTPUT | PULLUP | MODE7 */ ++ 0x034 0x2F /* gpio1_13 FAST | INPUT | PULLDOWN | MODE7 */ ++ >; ++ }; ++ ++ cryptocape_uart4_pins: pinmux_cryptocape_uart4_pins { ++ pinctrl-single,pins = < ++ 0x070 0x26 /* uart4_rxd | FAST | INPUT | MODE6 */ ++ 0x074 0x06 /* uart4_txd | FAST | OUTPUT | MODE6 */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart5>; /* uart4 to the BBB hardware */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cryptocape_uart4_pins>; ++ }; ++ }; ++ ++ ++ fragment@2 { ++ target = <&i2c2>; ++ ++ __overlay__ { ++ /* needed to avoid gripping by DTC */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* Real Time Clock */ ++ ds1307@68 { ++ compatible = "ds1307"; ++ reg = <0x68>; ++ }; ++ ++ /* TPM - Driver currently only available in 3.13.x */ ++ tpm_i2c_atmel@29 { ++ compatible = "tpm_i2c_atmel"; ++ reg = <0x29>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ cryptocape_gpio_helper { ++ compatible = "gpio-of-helper"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cryptocape_pins>; ++ ++ /* declare your gpios */ ++ atmega_rst { ++ gpio-name = "atmega_rst"; ++ gpio = <&gpio2 17 0x00>; /* gpio2 is gpio1 */ ++ output; ++ init-high; ++ }; ++ ++ ataes132_auth { ++ gpio-name = "test_input"; ++ gpio = <&gpio2 13 0x00>; /* gpio2 is gpio1 */ ++ input; ++ count-rising-edge; ++ count-falling-edge; ++ }; ++ }; ++ }; ++ }; ++}; +-- +1.9.1 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0029-Provides-a-sysfs-interface-to-the-eQEP-hardware-on-t.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0029-Provides-a-sysfs-interface-to-the-eQEP-hardware-on-t.patch new file mode 100644 index 00000000..41bbe40b --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0029-Provides-a-sysfs-interface-to-the-eQEP-hardware-on-t.patch @@ -0,0 +1,852 @@ +From 6956b3142caaecdc7257271c671e0d44620cbe0d Mon Sep 17 00:00:00 2001 +From: Nathaniel Lewis +Date: Mon, 2 Dec 2013 07:45:03 -0800 +Subject: [PATCH 29/30] Provides a sysfs interface to the eQEP hardware on the + AM33XX series SoCs + +Signed-off-by: Nathaniel Lewis +--- + arch/arm/boot/dts/am33xx.dtsi | 27 ++ + drivers/misc/Kconfig | 11 + + drivers/misc/Makefile | 1 + + drivers/misc/tieqep.c | 744 ++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 783 insertions(+) + create mode 100644 drivers/misc/tieqep.c + +diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi +index 5791c69..b8c9b33 100644 +--- a/arch/arm/boot/dts/am33xx.dtsi ++++ b/arch/arm/boot/dts/am33xx.dtsi +@@ -539,6 +539,15 @@ + ti,hwmods = "ehrpwm0"; + status = "disabled"; + }; ++ ++ eqep0: eqep@0x48300180 { ++ compatible = "ti,am33xx-eqep"; ++ reg = <0x48300180 0x80>; ++ interrupt-parent = <&intc>; ++ interrupts = <79>; ++ ti,hwmods = "eqep0"; ++ status = "disabled"; ++ }; + }; + + epwmss1: epwmss@48302000 { +@@ -567,6 +576,15 @@ + ti,hwmods = "ehrpwm1"; + status = "disabled"; + }; ++ ++ eqep1: eqep@0x48302180 { ++ compatible = "ti,am33xx-eqep"; ++ reg = <0x48302180 0x80>; ++ interrupt-parent = <&intc>; ++ interrupts = <88>; ++ ti,hwmods = "eqep1"; ++ status = "disabled"; ++ }; + }; + + epwmss2: epwmss@48304000 { +@@ -595,6 +613,15 @@ + ti,hwmods = "ehrpwm2"; + status = "disabled"; + }; ++ ++ eqep2: eqep@0x48304180 { ++ compatible = "ti,am33xx-eqep"; ++ reg = <0x48304180 0x80>; ++ interrupt-parent = <&intc>; ++ interrupts = <89>; ++ ti,hwmods = "eqep2"; ++ status = "disabled"; ++ }; + }; + + sham: sham@53100000 { +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 3c0cbf6..40a3eb9 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -511,6 +511,17 @@ config GROVE_I2C + help + Say Y here to support a minimal Grove I2C Motor Driver + ++config TIEQEP ++ tristate "EQEP Hardware quadrature encoder controller" ++ depends on SOC_AM33XX ++ select PWM_TIPWMSS ++ help ++ Driver support for the EQEP quadrature encoder controller AM33XX ++ TI SOC ++ ++ To compile this driver as a module, choose M here: the module ++ will be called tieqep. ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/cb710/Kconfig" +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index 72aef82..b10c476 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -51,4 +51,5 @@ obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ + obj-$(CONFIG_INTEL_MEI) += mei/ + obj-$(CONFIG_GPEVT) += gpevt.o + obj-$(CONFIG_GROVE_I2C) += grove-i2c.o ++obj-$(CONFIG_TIEQEP) += tieqep.o + obj-y += cape/ +diff --git a/drivers/misc/tieqep.c b/drivers/misc/tieqep.c +new file mode 100644 +index 0000000..e0ae946 +--- /dev/null ++++ b/drivers/misc/tieqep.c +@@ -0,0 +1,744 @@ ++/* ++ * TI eQEP driver for AM33xx devices ++ * ++ * Copyright (C) 2013 Nathaniel R. Lewis - http://teknoman117.wordpress.com/ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * sysfs entries ++ * - position = absolute - current position; relative - last latched value ++ * - mode => 0 - absolute; 1 - relative ++ * - period => sampling period for the hardware ++ * - enable => 0 - eQEP disabled, 1 - eQEP enabled ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++// Include the PWMSS subsystem headers, because this unit controls ++// whether our clock source is enabled, and if eQEP is to be ++// enabled, we need to start the clock ++#include "../pwm/pwm-tipwmss.h" ++ ++// eQEP register offsets from its base IO address ++#define QPOSCNT 0x0000 ++#define QPOSINIT 0x0004 ++#define QPOSMAX 0x0008 ++#define QPOSCMP 0x000C ++#define QPOSILAT 0x0010 ++#define QPOSSLAT 0x0014 ++#define QPOSLAT 0x0018 ++#define QUTMR 0x001C ++#define QUPRD 0x0020 ++#define QWDTMR 0x0024 ++#define QWDPRD 0x0026 ++#define QDECCTL 0x0028 ++#define QEPCTL 0x002A ++#define QCAPCTL 0x002C ++#define QPOSCTL 0x002E ++#define QEINT 0x0030 ++#define QFLG 0x0032 ++#define QCLR 0x0034 ++#define QFRC 0x0036 ++#define QEPSTS 0x0038 ++#define QCTMR 0x003A ++#define QCPRD 0x003C ++#define QCTMRLAT 0x003E ++#define QCPRDLAT 0x0040 ++#define QREVID 0x005C ++ ++// Bits for the QDECTL register ++#define QSRC1 (0x0001 << 15) ++#define QSRC0 (0x0001 << 14) ++#define SOEN (0x0001 << 13) ++#define SPSEL (0x0001 << 12) ++#define XCR (0x0001 << 11) ++#define SWAP (0x0001 << 10) ++#define IGATE (0x0001 << 9) ++#define QAP (0x0001 << 8) ++#define QBP (0x0001 << 7) ++#define QIP (0x0001 << 6) ++#define QSP (0x0001 << 5) ++ ++// Bits for the QEPCTL register ++#define FREESOFT1 (0x0001 << 15) ++#define FREESOFT0 (0x0001 << 14) ++#define PCRM1 (0x0001 << 13) ++#define PCRM0 (0x0001 << 12) ++#define SEI1 (0x0001 << 11) ++#define SEI0 (0x0001 << 10) ++#define IEI1 (0x0001 << 9) ++#define IEI0 (0x0001 << 8) ++#define SWI (0x0001 << 7) ++#define SEL (0x0001 << 6) ++#define IEL1 (0x0001 << 5) ++#define IEL0 (0x0001 << 4) ++#define PHEN (0x0001 << 3) ++#define QCLM (0x0001 << 2) ++#define UTE (0x0001 << 1) ++#define WDE (0x0001 << 0) ++ ++// Bits for the QCAPCTL register ++#define CEN (0x0001 << 15) ++#define CCPS2 (0x0001 << 6) ++#define CCPS0 (0x0001 << 5) ++#define CCPS1 (0x0001 << 4) ++#define UPPS3 (0x0001 << 3) ++#define UPPS2 (0x0001 << 2) ++#define UPPS1 (0x0001 << 1) ++#define UPPS0 (0x0001 << 0) ++ ++// Bits for the QPOSCTL register ++#define PCSHDW (0x0001 << 15) ++#define PCLOAD (0x0001 << 14) ++#define PCPOL (0x0001 << 13) ++#define PCE (0x0001 << 12) ++#define PCSPW11 (0x0001 << 11) ++#define PCSPW10 (0x0001 << 10) ++#define PCSPW9 (0x0001 << 9) ++#define PCSPW8 (0x0001 << 8) ++#define PCSPW7 (0x0001 << 7) ++#define PCSPW6 (0x0001 << 6) ++#define PCSPW5 (0x0001 << 5) ++#define PCSPW4 (0x0001 << 4) ++#define PCSPW3 (0x0001 << 3) ++#define PCSPW2 (0x0001 << 2) ++#define PCSPW1 (0x0001 << 1) ++#define PCSPW0 (0x0001 << 0) ++ ++// Bits for the interrupt registers ++#define EQEP_INTERRUPT_MASK (0x0FFF) ++#define UTOF (0x0001 << 11) ++ ++// Bits to control the clock in the PWMSS subsystem ++#define PWMSS_EQEPCLK_EN BIT(4) ++#define PWMSS_EQEPCLK_STOP_REQ BIT(5) ++#define PWMSS_EQEPCLK_EN_ACK BIT(4) ++ ++// Modes for the eQEP unit ++// Absolute - the position entry represents the current position of the encoder. ++// Poll this value and it will be notified every period nanoseconds ++// Relative - the position entry represents the last latched position of the encoder ++// This value is latched every period nanoseconds and the internal counter ++// is subsequenty reset ++#define TIEQEP_MODE_ABSOLUTE 0 ++#define TIEQEP_MODE_RELATIVE 1 ++ ++// Structure defining the characteristics of the eQEP unit ++struct eqep_chip ++{ ++ // Platform device for this eQEP unit ++ struct platform_device *pdev; ++ ++ // Pointer to the base of the memory of the eQEP unit ++ void __iomem *mmio_base; ++ ++ // SYSCLKOUT to the eQEP unit ++ u32 clk_rate; ++ ++ // IRQ for the eQEP unit ++ u16 irq; ++ ++ // Mode of the eQEP unit ++ u8 mode; ++ ++ // work stuct for the notify userspace work ++ struct work_struct notify_work; ++ ++ // Backup for driver suspension ++ u16 prior_qepctl; ++ u16 prior_qeint; ++}; ++ ++// Notify userspace work ++void notify_handler (struct work_struct *work) ++{ ++ // Get a reference to the eQEP driver ++ struct eqep_chip *eqep = container_of(work, struct eqep_chip, notify_work); ++ ++ // Notify the userspace ++ sysfs_notify(&eqep->pdev->dev.kobj, NULL, "position"); ++} ++ ++// eQEP Interrupt handler ++static irqreturn_t eqep_irq_handler(int irq, void *dev_id) ++{ ++ // Get the instance information ++ struct platform_device *pdev = dev_id; ++ struct eqep_chip *eqep = platform_get_drvdata(pdev); ++ ++ // Get the interrupt flags ++ u16 iflags = readw(eqep->mmio_base + QFLG) & EQEP_INTERRUPT_MASK; ++ ++ // Check the interrupt source(s) ++ if(iflags & UTOF) ++ { ++ // Handle the unit timer overflow interrupt by notifying any potential pollers ++ schedule_work(&eqep->notify_work); ++ } ++ ++ // Clear interrupt flags (write back triggered flags to the clear register) ++ writew(iflags, eqep->mmio_base + QCLR); ++ ++ // Return that the IRQ was handled successfully ++ return IRQ_HANDLED; ++} ++ ++// Function to read whether the eQEP unit is enabled or disabled ++static ssize_t eqep_get_enabled(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ // Get the instance structure ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ ++ // Read the qep control register and mask all but the enabled bit ++ u16 enabled = readw(eqep->mmio_base + QEPCTL) & PHEN; ++ ++ // Return the target in string format ++ return sprintf(buf, "%u\n", (enabled) ? 1 : 0); ++} ++ ++// Function to set if the eQEP is enabled ++static ssize_t eqep_set_enabled(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) ++{ ++ // Get the instance structure ++ int rc; ++ u16 val; ++ u8 enabled; ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ ++ // Convert the input string to an 8 bit uint ++ if ((rc = kstrtou8(buf, 0, &enabled))) ++ return rc; ++ ++ // Get the existing state of QEPCTL ++ val = readw(eqep->mmio_base + QEPCTL); ++ ++ // If we passed a number that is not 0, enable the eQEP ++ if(enabled) ++ { ++ // Enable the eQEP (Set PHEN in QEPCTL) ++ val = val | PHEN; ++ } else ++ { ++ // Disable the eQEP (Clear PHEN in QEPCTL) ++ val = val & ~PHEN; ++ } ++ ++ // Write flags back to control register ++ writew(val, eqep->mmio_base + QEPCTL); ++ ++ // Return buffer length consumed (all) ++ return count; ++} ++ ++// Function to read the current position of the eQEP ++static ssize_t eqep_get_position(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ // Get the instance structure ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ ++ // A variable to return the position with ++ s32 position = 0; ++ ++ // Check the mode ++ if(eqep->mode == TIEQEP_MODE_ABSOLUTE) ++ { ++ // If we are in absolute mode, we need the current value of the eQEP hardware ++ position = readl(eqep->mmio_base + QPOSCNT); ++ } else if(eqep->mode == TIEQEP_MODE_RELATIVE) ++ { ++ // If we are in relative mode, we need the last latched value of the eQEP hardware ++ position = readl(eqep->mmio_base + QPOSLAT); ++ } ++ ++ // Return the target in string format ++ return sprintf(buf, "%d\n", position); ++} ++ ++// Function to set the position of the eQEP hardware ++static ssize_t eqep_set_position(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) ++{ ++ // Get the instance structure ++ int rc; ++ s32 position; ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ ++ // Convert the input string to an 8 bit uint ++ if ((rc = kstrtos32(buf, 0, &position))) ++ return rc; ++ ++ // If we are in absolute mode, set the position of the encoder, discard relative mode because thats pointless ++ if(eqep->mode == TIEQEP_MODE_ABSOLUTE) ++ { ++ // If we are in absolute mode, we need the current value of the eQEP hardware ++ writel(position, eqep->mmio_base + QPOSCNT); ++ } ++ ++ // Return buffer length consumed (all) ++ return count; ++} ++ ++// Function to read the period of the unit time event timer ++static ssize_t eqep_get_timer_period(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ // Get the instance structure ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ u64 period = 0; ++ ++ // Check if the period timer is enabled, if not, return 0 ++ if(!(readw(eqep->mmio_base + QEPCTL) & UTE)) ++ { ++ return sprintf(buf, "0\n"); ++ } ++ ++ // Convert from counts per interrupt back into period_ns ++ period = readl(eqep->mmio_base + QUPRD); ++ period = period * NSEC_PER_SEC; ++ do_div(period, eqep->clk_rate); ++ ++ // Otherwise write out the data ++ return sprintf(buf, "%llu\n", period); ++} ++ ++// Function to set the unit timer period. 0 = off, greater than zero sets the period ++static ssize_t eqep_set_timer_period(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) ++{ ++ int rc; ++ u16 tmp; ++ u64 period; ++ ++ // Get the instance structure ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ ++ // Convert the passed string to a 64 bit uint ++ if((rc = kstrtou64(buf, 0, &period))) ++ return rc; ++ ++ // Disable the unit timer before modifying its period register ++ tmp = readw(eqep->mmio_base + QEPCTL); ++ tmp = tmp & ~UTE & ~QCLM; ++ writew(tmp, eqep->mmio_base + QEPCTL); ++ ++ // Zero the unit timer counter register ++ writel(0x0, eqep->mmio_base + QUTMR); ++ ++ // If we want the timer enabled (a period that is non zero has been passed) ++ if(period) ++ { ++ // Otherwise calculate the period ++ period = period * eqep->clk_rate; ++ do_div(period, NSEC_PER_SEC); ++ ++ // Set this period into the unit timer period register ++ writel(period & 0x00000000FFFFFFFF, eqep->mmio_base + QUPRD); ++ ++ // Enable the unit timer, and latch QPOSLAT to QPOSCNT on overflow ++ tmp = readw(eqep->mmio_base + QEPCTL); ++ tmp = tmp | UTE | QCLM; ++ writew(tmp, eqep->mmio_base + QEPCTL); ++ } ++ ++ // Return consumed buffer count ++ return count; ++} ++ ++// Function to read the mode of the eQEP hardware ++static ssize_t eqep_get_mode(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ // Get the instance structure ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ ++ // Return the mode ++ return sprintf(buf, "%u\n", eqep->mode); ++} ++ ++// Function to set the mode of the eQEP hardware ++static ssize_t eqep_set_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) ++{ ++ // Get the instance structure ++ int rc; ++ u16 val; ++ u8 tmp_mode; ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ ++ // Convert the input string to an 8 bit uint ++ if ((rc = kstrtou8(buf, 0, &tmp_mode))) ++ return rc; ++ ++ // Get the existing state of QEPCTL ++ val = readw(eqep->mmio_base + QEPCTL); ++ ++ // Check the mode that was passed ++ if(tmp_mode == TIEQEP_MODE_ABSOLUTE) ++ { ++ // In absolute mode, we don't want to reset the intenal hardware based on time, ++ // so disable the unit timer position reset (Set PCRM[1:0] = 0) ++ val = val & ~PCRM1 & ~PCRM0; ++ ++ // Store the mode as absolute ++ eqep->mode = TIEQEP_MODE_ABSOLUTE; ++ } else if(tmp_mode == TIEQEP_MODE_RELATIVE) ++ { ++ // In relative mode, we want to latch the value of the eQEP hardware on the ++ // overflow of the unit timer. So enable the unit timer position reset ++ // (Set PCRM[1:0] = 3) ++ val = val | PCRM1 | PCRM0; ++ ++ // Store the mode as relative ++ eqep->mode = TIEQEP_MODE_RELATIVE; ++ } ++ ++ // Write the new value back to the control register ++ writew(val, eqep->mmio_base + QEPCTL); ++ ++ // Return buffer length consumed (all) ++ return count; ++} ++ ++// Bind read/write functions to sysfs entries ++static DEVICE_ATTR(enabled, 0644, eqep_get_enabled, eqep_set_enabled); ++static DEVICE_ATTR(position, 0644, eqep_get_position, eqep_set_position); ++static DEVICE_ATTR(period, 0644, eqep_get_timer_period, eqep_set_timer_period); ++static DEVICE_ATTR(mode, 0644, eqep_get_mode, eqep_set_mode); ++ ++// Array holding all of the sysfs entries ++static const struct attribute *eqep_attrs[] = { ++ &dev_attr_enabled.attr, ++ &dev_attr_position.attr, ++ &dev_attr_period.attr, ++ &dev_attr_mode.attr, ++ NULL, ++}; ++ ++// Driver function group ++static const struct attribute_group eqep_device_attr_group = { ++ .attrs = (struct attribute **) eqep_attrs, ++}; ++ ++// Driver compatibility list ++static struct of_device_id eqep_of_match[] = ++{ ++ { .compatible = "ti,am33xx-eqep" }, ++ { } ++}; ++ ++// Register our compatibilities for device trees ++MODULE_DEVICE_TABLE(of, eqep_of_match); ++ ++// Create an instance of the eQEP driver ++static int eqep_probe(struct platform_device *pdev) ++{ ++ struct resource *r; ++ struct clk *clk; ++ struct eqep_chip *eqep; ++ struct pinctrl *pinctrl; ++ int ret; ++ u64 period; ++ u16 status; ++ u32 value; ++ ++ // Select any default pins possible provided through the device tree ++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev); ++ if (IS_ERR(pinctrl)) ++ { ++ dev_warn(&pdev->dev, "unable to select pin group\n"); ++ } ++ ++ // Allocate a eqep_driver object ++ eqep = devm_kzalloc(&pdev->dev, sizeof(struct eqep_chip), GFP_KERNEL); ++ if (!eqep) { ++ dev_err(&pdev->dev, "failed to allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ // Get a handle to the system clock object ++ clk = devm_clk_get(&pdev->dev, "fck"); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "failed to get clock\n"); ++ return PTR_ERR(clk); ++ } ++ ++ // Get the frequency of the system clock ++ eqep->clk_rate = clk_get_rate(clk); ++ if (!eqep->clk_rate) { ++ dev_err(&pdev->dev, "failed to get clock rate\n"); ++ return -EINVAL; ++ } ++ ++ // Get a resource containing the IRQ for this eQEP controller ++ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (unlikely(!r)) { ++ dev_err(&pdev->dev, "Invalid IRQ resource\n"); ++ return -ENODEV; ++ } ++ ++ // Store the irq ++ eqep->irq = r->start; ++ ++ // Get a resource containing the requested (from DT) memory address and range of eQEP controller ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!r) { ++ dev_err(&pdev->dev, "no memory resource defined\n"); ++ return -ENODEV; ++ } ++ ++ // Remap the eQEP controller memory into our own memory space ++ eqep->mmio_base = devm_request_and_ioremap(&pdev->dev, r); ++ if (!eqep->mmio_base) ++ return -EADDRNOTAVAIL; ++ ++ // Store the platform device in our eQEP data structure for later usage ++ eqep->pdev = pdev; ++ ++ // Subscribe to the eQEP interrupt ++ if (request_irq(eqep->irq, eqep_irq_handler, IRQF_IRQPOLL, "eqep_interrupt", pdev)) ++ { ++ dev_err(&pdev->dev, "unable to request irq for eQEP\n"); ++ return -ENODEV; ++ } ++ ++ // Register controls to sysfs ++ if (sysfs_create_group(&pdev->dev.kobj, &eqep_device_attr_group)) ++ { ++ dev_err(&pdev->dev, "sysfs creation failed\n"); ++ return -EINVAL; ++ } ++ ++ // Read decoder control settings ++ status = readw(eqep->mmio_base + QDECCTL); ++ ++ // Quadrature mode or direction mode ++ if(of_property_read_u32(pdev->dev.of_node, "count_mode", &value)) ++ status = status & ~QSRC1 & ~QSRC0; ++ else ++ status = ((value) ? status | QSRC0 : status & ~QSRC0) & ~QSRC1; ++ ++ // Should we invert the qa input ++ if(of_property_read_u32(pdev->dev.of_node, "invert_qa", &value)) ++ status = status & ~QAP; ++ else ++ status = (value) ? status | QAP : status & ~QAP; ++ ++ // Should we invert the qb input ++ if(of_property_read_u32(pdev->dev.of_node, "invert_qb", &value)) ++ status = status & ~QBP; ++ else ++ status = (value) ? status | QBP : status & ~QBP; ++ ++ // Should we invert the index input ++ if(of_property_read_u32(pdev->dev.of_node, "invert_qi", &value)) ++ status = status & ~QIP; ++ else ++ status = (value) ? status | QIP : status & ~QIP; ++ ++ // Should we invert the strobe input ++ if(of_property_read_u32(pdev->dev.of_node, "invert_qs", &value)) ++ status = status & ~QSP; ++ else ++ status = (value) ? status | QSP : status & ~QSP; ++ ++ // Should we swap the cha and chb inputs ++ if(of_property_read_u32(pdev->dev.of_node, "swap_inputs", &value)) ++ status = status & ~SWAP; ++ else ++ status = (value) ? status | SWAP : status & ~SWAP; ++ ++ // Write the decoder control settings back to the control register ++ writew(status, eqep->mmio_base + QDECCTL); ++ ++ // Initialize the position counter to zero ++ writel(0, eqep->mmio_base + QPOSINIT); ++ ++ // This is pretty ingenious if I do say so myself. The eQEP subsystem has a register ++ // that defined the maximum value of the encoder as an unsigned. If the counter is zero ++ // and decrements again, it is set to QPOSMAX. If you cast -1 (signed int) to ++ // to an unsigned, you will notice that -1 == UINT_MAX. So when the counter is set to this ++ // maximum position, when read into a signed int, it will equal -1. Two's complement for ++ // the WIN!! ++ writel(-1, eqep->mmio_base + QPOSMAX); ++ ++ // Enable some interrupts ++ status = readw(eqep->mmio_base + QEINT); ++ status = status | UTOF; ++ // UTOF - Unit Time Period interrupt. This is triggered when the unit timer period expires ++ // ++ writew(status, eqep->mmio_base + QEINT); ++ ++ // Calculate the timer ticks per second ++ period = 1000000000; ++ period = period * eqep->clk_rate; ++ do_div(period, NSEC_PER_SEC); ++ ++ // Set this period into the unit timer period register ++ writel(period & 0x00000000FFFFFFFF, eqep->mmio_base + QUPRD); ++ ++ // Enable the eQEP with basic position counting turned on ++ status = readw(eqep->mmio_base + QEPCTL); ++ status = status | PHEN | IEL0 | SWI | UTE | QCLM; ++ // PHEN - Quadrature position counter enable bit ++ // IEL0 - Latch QPOSILAT on index signal. This can be rising or falling, IEL[1:0] = 0 is reserved ++ // SWI - Software initialization of position count register. Basic set QPOSCNT <= QPOSINIT ++ // UTE - unit timer enable ++ // QCLM - latch QPOSLAT to QPOSCNT upon unit timer overflow ++ writew(status, eqep->mmio_base + QEPCTL); ++ ++ // We default to absolute mode ++ eqep->mode = TIEQEP_MODE_ABSOLUTE; ++ ++ // Enable the power management runtime ++ pm_runtime_enable(&pdev->dev); ++ ++ // Increment the device usage count and run pm_runtime_resume() ++ pm_runtime_get_sync(&pdev->dev); ++ ++ // Enable the clock to the eQEP unit ++ status = pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EQEPCLK_EN); ++ ++ // If we failed to enable the clocks, fail out ++ if (!(status & PWMSS_EQEPCLK_EN_ACK)) ++ { ++ dev_err(&pdev->dev, "PWMSS config space clock enable failed\n"); ++ ret = -EINVAL; ++ goto pwmss_clk_failure; ++ } ++ ++ // Initialize the notify work struture ++ INIT_WORK(&eqep->notify_work, notify_handler); ++ ++ // Decrement the device usage count (twice) and run pm_runtime_idle() if zero ++ pm_runtime_put_sync(&pdev->dev); ++ ++ // Set the platform driver data to the data object we've been creating for the eQEP unit ++ platform_set_drvdata(pdev, eqep); ++ ++ // Success! ++ //printk(KERN_INFO "EQEP irq = %d, system clock = %u\n", eqep->irq, eqep->clk_rate); ++ return 0; ++ ++ // If a failure occurred, stop the runtime power management ++pwmss_clk_failure: ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ return ret; ++} ++ ++// Remove an instance of the eQEP driver ++static int eqep_remove(struct platform_device *pdev) ++{ ++ // Get the eQEP driver data from the platform device structure ++ struct eqep_chip *eqep = platform_get_drvdata(pdev); ++ ++ // Cancel work ++ cancel_work_sync(&eqep->notify_work); ++ ++ // Unmap from sysfs ++ sysfs_remove_group(&pdev->dev.kobj, &eqep_device_attr_group); ++ ++ // Release important assets ++ free_irq(eqep->irq, pdev); ++ ++ // Increment the device usage count and run pm_runtime_resume() ++ pm_runtime_get_sync(&pdev->dev); ++ ++ // Disable the eQEP clock ++ pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EQEPCLK_STOP_REQ); ++ ++ // Decrement the device usage count (twice) and run pm_runtime_idle() if zero ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_put_sync(&pdev->dev); ++ ++ // Disable the runtime power management of this device ++ pm_runtime_disable(&pdev->dev); ++ ++ // Return success ++ return 0; ++} ++ ++// Power management suspend device ++static int eqep_suspend(struct device *dev) ++{ ++ // Get the eqep driver information ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ u16 tmp; ++ ++ // Shut down interrupts ++ eqep->prior_qeint = readw(eqep->mmio_base + QEINT); ++ tmp = eqep->prior_qeint & ~UTOF; ++ // UTOF - Unit Time Period interrupt. ++ writew(tmp, eqep->mmio_base + QEINT); ++ ++ // Get the existing state of QEPCTL ++ eqep->prior_qepctl = readw(eqep->mmio_base + QEPCTL); ++ ++ // Disable eQEP controller ++ writew(eqep->prior_qepctl & ~PHEN, eqep->mmio_base + QEPCTL); ++ ++ // Decrement the device usage count and run pm_runtime_idle() if zero ++ pm_runtime_put_sync(dev); ++ ++ // Return success ++ return 0; ++} ++ ++// Power management wake device back up ++static int eqep_resume(struct device *dev) ++{ ++ // Get the eqep driver information ++ struct eqep_chip *eqep = dev_get_drvdata(dev); ++ ++ // Restore interrupt enabled register ++ writew(eqep->prior_qeint, eqep->mmio_base + QEINT); ++ ++ // Restore prior qep control register ++ writew(eqep->prior_qepctl, eqep->mmio_base + QEPCTL); ++ ++ // Increment the device usage count and run pm_runtime_resume() ++ pm_runtime_get_sync(dev); ++ ++ // Success ++ return 0; ++} ++ ++// create pm functions object ++static SIMPLE_DEV_PM_OPS(eqep_pm_ops, eqep_suspend, eqep_resume); ++ ++// Platform driver information ++static struct platform_driver eqep_driver = { ++ .driver = { ++ .name = "eqep", ++ .owner = THIS_MODULE, ++ .pm = &eqep_pm_ops, ++ .of_match_table = eqep_of_match, ++ }, ++ .probe = eqep_probe, ++ .remove = eqep_remove, ++}; ++ ++// Register this platform driver ++module_platform_driver(eqep_driver); ++ ++// Module information ++MODULE_DESCRIPTION("TI eQEP driver"); ++MODULE_AUTHOR("Nathaniel R. Lewis"); ++MODULE_LICENSE("GPL"); +-- +1.9.2 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0030-capes-add-bone_eqep-from-https-github.com-Teknoman11.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0030-capes-add-bone_eqep-from-https-github.com-Teknoman11.patch new file mode 100644 index 00000000..b75fe56a --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0030-capes-add-bone_eqep-from-https-github.com-Teknoman11.patch @@ -0,0 +1,226 @@ +From dd2a8e8264b7b3bf519306fe8d2039e397ba3dfa Mon Sep 17 00:00:00 2001 +From: Robert Nelson +Date: Thu, 24 Apr 2014 15:43:04 -0500 +Subject: [PATCH 30/30] capes: add bone_eqep from + https://github.com/Teknoman117/beaglebot/tree/master/encoders/dts + +Signed-off-by: Robert Nelson +--- + firmware/Makefile | 5 +++- + firmware/capes/bone_eqep0-00A0.dts | 58 ++++++++++++++++++++++++++++++++++++++ + firmware/capes/bone_eqep1-00A0.dts | 57 +++++++++++++++++++++++++++++++++++++ + firmware/capes/bone_eqep2-00A0.dts | 57 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 176 insertions(+), 1 deletion(-) + create mode 100644 firmware/capes/bone_eqep0-00A0.dts + create mode 100644 firmware/capes/bone_eqep1-00A0.dts + create mode 100644 firmware/capes/bone_eqep2-00A0.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index 299b3a5..f399380 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -202,7 +202,10 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + cape-universal-00A0.dtbo \ + cape-universaln-00A0.dtbo \ + cape-bone-ibb-00A0.dtbo \ +- BB-BONE-CRYPTO-00A0.dtbo ++ BB-BONE-CRYPTO-00A0.dtbo \ ++ bone_eqep0-00A0.dtbo \ ++ bone_eqep1-00A0.dtbo \ ++ bone_eqep2-00A0.dtbo + + # the geiger cape + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \ +diff --git a/firmware/capes/bone_eqep0-00A0.dts b/firmware/capes/bone_eqep0-00A0.dts +new file mode 100644 +index 0000000..d1b7760 +--- /dev/null ++++ b/firmware/capes/bone_eqep0-00A0.dts +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2013 Nathaniel R. Lewis - http://teknoman117.wordpress.com/ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Enable eQEP0 on the Beaglebone Black - incompatible with BB White because ++ * most of the eQEP0 pins on Beaglebone white are not broken out. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "bone_eqep0"; ++ version = "00A0"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ pinctrl_eqep0: pinctrl_eqep0_pins { ++ pinctrl-single,pins = < ++ 0x1A8 0x21 /* P9_41 = GPIO3_20 = EQEP0_index, MODE1 */ ++ 0x1AC 0x21 /* P9_25 = GPIO3_21 = EQEP0_strobe, MODE1 */ ++ 0x1A0 0x31 /* P9_42 = GPIO3_18 = EQEP0A_in, MODE1 */ ++ 0x1A4 0x31 /* P9_27 = GPIO3_19 = EQEP0B_in, MODE1 */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&epwmss0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&eqep0>; ++ __overlay__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_eqep0>; ++ ++ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */ ++ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */ ++ invert_qa = <1>; /* Should we invert the channel A input? */ ++ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */ ++ invert_qi = <0>; /* Should we invert the index input? */ ++ invert_qs = <0>; /* Should we invert the strobe input? */ ++ ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/firmware/capes/bone_eqep1-00A0.dts b/firmware/capes/bone_eqep1-00A0.dts +new file mode 100644 +index 0000000..1760fce +--- /dev/null ++++ b/firmware/capes/bone_eqep1-00A0.dts +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2013 Nathaniel R. Lewis - http://teknoman117.wordpress.com/ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Enable eQEP1 on the Beaglebone White and Black ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "bone_eqep1"; ++ version = "00A0"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ pinctrl_eqep1: pinctrl_eqep1_pins { ++ pinctrl-single,pins = < ++ 0x0D8 0x22 /* P8_31 = GPIO0_10 = EQEP1_index, MODE2 */ ++ 0x0DC 0x22 /* P8_32 = GPIO0_11 = EQEP1_strobe, MODE2 */ ++ 0x0D4 0x32 /* P8_33 = GPIO0_9 = EQEP1B_in, MODE2 */ ++ 0x0D0 0x32 /* P8_35 = GPIO0_8 = EQEP1A_in, MODE2 */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&epwmss1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&eqep1>; ++ __overlay__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_eqep1>; ++ ++ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */ ++ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */ ++ invert_qa = <1>; /* Should we invert the channel A input? */ ++ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */ ++ invert_qi = <0>; /* Should we invert the index input? */ ++ invert_qs = <0>; /* Should we invert the strobe input? */ ++ ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/firmware/capes/bone_eqep2-00A0.dts b/firmware/capes/bone_eqep2-00A0.dts +new file mode 100644 +index 0000000..83f9de7 +--- /dev/null ++++ b/firmware/capes/bone_eqep2-00A0.dts +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2013 Nathaniel R. Lewis - http://teknoman117.wordpress.com/ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Enable eQEP2 on the Beaglebone White and Black ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "bone_eqep2"; ++ version = "00A0"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ pinctrl_eqep2: pinctrl_eqep2_pins { ++ pinctrl-single,pins = < ++ 0x0B8 0x23 /* P8_39 = GPIO2_12 = EQEP2_index, MODE3 */ ++ 0x0BC 0x23 /* P8_40 = GPIO2_13 = EQEP2_strobe, MODE3 */ ++ 0x0B0 0x33 /* P8_41 = GPIO2_10 = EQEP2A_in, MODE3 */ ++ 0x0B4 0x33 /* P8_42 = GPIO2_11 = EQEP2B_in, MODE3 */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&epwmss2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&eqep2>; ++ __overlay__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_eqep2>; ++ ++ count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */ ++ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */ ++ invert_qa = <1>; /* Should we invert the channel A input? */ ++ invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */ ++ invert_qi = <0>; /* Should we invert the index input? */ ++ invert_qs = <0>; /* Should we invert the strobe input? */ ++ ++ status = "okay"; ++ }; ++ }; ++}; +-- +1.9.2 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0031-Adding-Logibone-to-cape-support-list.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0031-Adding-Logibone-to-cape-support-list.patch new file mode 100644 index 00000000..6aba038e --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0031-Adding-Logibone-to-cape-support-list.patch @@ -0,0 +1,40 @@ +From 9f02c7cc1fcf6738c12937fbc544a51ed3a5a22b Mon Sep 17 00:00:00 2001 +From: Jonathan Piat +Date: Mon, 28 Apr 2014 23:14:32 +0200 +Subject: [PATCH 3/3] Adding Logibone to cape support list + +--- + arch/arm/boot/dts/am335x-bone-common.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi +index 4e3c475..6984060 100644 +--- a/arch/arm/boot/dts/am335x-bone-common.dtsi ++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi +@@ -210,6 +210,7 @@ + manufacturer = "Adafruit"; + part-number = "BB-BONE-GPS-01"; + }; ++ + + /* Beaglebone black has it soldered on */ + slot@100 { +@@ -406,6 +407,15 @@ + }; + }; + ++ /* LOGIBONE cape */ ++ cape@16 { ++ part-number = "BB-BONE-LOGIBONE"; ++ version@00R1 { ++ version = "00R1"; ++ dtbo = "BB-BONE-LOGIBONE-00R1.dtbo"; ++ }; ++ }; ++ + }; + }; + +-- +1.7.9.5 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0032-beaglebone-capes-Added-CBB-Relay-cape-dt-overlay.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0032-beaglebone-capes-Added-CBB-Relay-cape-dt-overlay.patch new file mode 100644 index 00000000..d440d9e0 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0032-beaglebone-capes-Added-CBB-Relay-cape-dt-overlay.patch @@ -0,0 +1,377 @@ +From 1d93a6c3b2e9dc2d40d06eb22b966b0541c4cfb3 Mon Sep 17 00:00:00 2001 +From: Alexander Hiam +Date: Fri, 9 May 2014 13:04:13 -0400 +Subject: [PATCH 32/32] beaglebone capes: Added CBB-Relay cape dt overlay + +Added Device Tree overlay for the CBB-Relay cape and fixed a copy and paste +error in a comment in /firmware/Makefile. + +signed-off-by: Alexander Hiam +--- + firmware/Makefile | 6 +- + firmware/capes/CBB-Relay-00A0.dts | 331 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 336 insertions(+), 1 deletion(-) + create mode 100644 firmware/capes/CBB-Relay-00A0.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index f399380..90d4ad2 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -231,12 +231,16 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + # the Tester cape (tester-side) + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-tester-00A0.dtbo + +-# the CBB-Serial cape (tester-side) ++# the CBB-Serial cape + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + cape-CBB-Serial-r01.dtbo \ + BB-UART2-RTSCTS-00A0.dtbo \ + BB-UART4-RTSCTS-00A0.dtbo + ++# the CBB-Relay cape ++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ ++ CBB-Relay-00A0.dtbo ++ + # the virtual peripheral capes for the UARTs + # UART3 is not routed to the connectors, no cape for it + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ +diff --git a/firmware/capes/CBB-Relay-00A0.dts b/firmware/capes/CBB-Relay-00A0.dts +new file mode 100644 +index 0000000..f7f4edd +--- /dev/null ++++ b/firmware/capes/CBB-Relay-00A0.dts +@@ -0,0 +1,331 @@ ++/* CBB-Relay-00A0.dts ++ * Logic Supply - http://logicsupply.com ++ * ++ * This is the Device Tree overlay for the CBB-Relay BeagleBone and ++ * BeagleBone Black cape. ++ * ++ * Upon loading, 6 sysfs kernel driver interfaces will be created ++ * (The values of 'X' in the paths below will change depending on ++ * your system): ++ * ++ * - /sys/devices/ocp.X/CBB-Relay-ain.X/ ++ * - AIN1 : Reading this file will give the voltage in mV on AIN0, ++ * accounting for the CBB-Relay's /10 divider ++ * - AIN5 : Reading this file will give the voltage in mV on AIN1 ++ * ++ * - /sys/devices/ocp.X/CBB-Relay-in1-pull.X/ ++ * - state : The following strings may be written to this file ++ * (without quotes): ++ * - "pullup" : enables pullup on in1 (default state) ++ * - "nopull" : disables pullup/pulldown on in1 ++ * ++ * - /sys/devices/ocp.X/CBB-Relay-in2-pull.X/ ++ * - state : See above ++ * ++ * - /sys/devices/ocp.X/CBB-Relay-in3-pull.X/ ++ * - state : See above ++ * ++ * - /sys/devices/ocp.X/CBB-Relay-in4-pull.X/ ++ * - state : See above ++ * ++ * - /sys/devices/ocp.X/CBB-Relay-servo1.X/ ++ * - duty : Write desired pulse width in nanoseconds ++ * (initial value is 1000000 [1ms]) ++ * - period : Write desired period in nanoseconds ++ * (initial value is 20000000 [50Hz]) ++ * - polarity : Write 0 for normally low, 1 for normally high ++ * (initial value is 0) ++ * - run : Write 1 to enable output, 0 to disable ++ * (initial value is 0) ++ * ++ * Copyright (c) 2014 - Logic Supply (http://logicsupply.com) ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ part-number = "CBB-Relay"; ++ version = "00A0"; ++ ++ /* State the resources this cape uses - used to check cape compatibility. */ ++ exclusive-use = ++ /* the pin header uses */ ++ "P8.26", /* Relay K1 - GPIO1_29 */ ++ "P9.27", /* Relay K2 - GPIO3_19 */ ++ ++ "P9.24", /* Blue LED - GPIO0_15 */ ++ ++ "P9.42", /* out1 - GPIO0_7 (eCAP?) */ ++ "P9.22", /* out2 - GPIO0_2 (eCAP?) */ ++ "P9.21", /* out3 - GPIO0_3 (eCAP?) */ ++ "P9.16", /* out4 - GPIO1_19 (eCAP?) */ ++ ++ "P8.11", /* in1 - GPIO1_13 */ ++ "P8.12", /* in2 - GPIO1_12 */ ++ "P8.14", /* in3 - GPIO0_26 */ ++ "P8.15", /* in4 - GPIO1_15 */ ++ ++ "P9.14", /* servo1 */ ++ ++ "P9.40", /* ain1 (/10) */ ++ "P9.36", /* ain5 (pot) */ ++ ++ /* the hardware IP uses */ ++ "tscadc1", ++ "tscadc5", ++ "ehrpwm1A"; ++ ++ /*----- Start pinmux -----*/ ++ ++ fragment@0 { ++ /* Sets pinmux for relays. */ ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ cbb_relay_relay_pins: pinmux_cbb_relay_relay_pins { ++ pinctrl-single,pins = < ++ 0x07c 0x7 /* gpmc_csn0 - MODE7 (GPIO1_29) */ ++ 0x1a4 0x7 /* mcasp0_fsr - MODE7 (GPIO3_19) */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ /* Sets pinmux for general purpose outputs. */ ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ cbb_relay_out_pins: pinmux_cbb_relay_out_pins { ++ pinctrl-single,pins = < ++ 0x164 0x7 /* eCAP0_in_PWM0_out - MODE7 (GPIO0_7) */ ++ 0x150 0x7 /* spi0_sclk - MODE7 (GPIO0_2) */ ++ 0x154 0x7 /* spi0_d0 - MODE7 (GPIO0_3) */ ++ 0x04c 0x7 /* gpmc_a3 - MODE7 (GPIO1_19) */ ++ 0x184 0x7 /* uart1_txd - MODE7 (GPIO0_15) - blue LED */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ /* Defines pinmux modes for general purpose inputs. */ ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ cbb_relay_in1_nopull: pinmux_cbb_relay_in1_nopull { ++ pinctrl-single,pins = < ++ 0x034 0x2f /* gpmc_ad13 - rx enabled | nopull | - MODE7 (GPIO1_13) */ ++ >; ++ }; ++ cbb_relay_in1_pullup: pinmux_cbb_relay_in1_pullup { ++ pinctrl-single,pins = < ++ 0x034 0x37 /* gpmc_ad13 - rx enabled | pullup | - MODE7 (GPIO1_13) */ ++ >; ++ }; ++ cbb_relay_in1_pulldown: pinmux_cbb_relay_in1_pulldown { ++ pinctrl-single,pins = < ++ 0x034 0x27 /* gpmc_ad13 - rx enabled | pulldown | - MODE7 (GPIO1_13) */ ++ >; ++ }; ++ ++ cbb_relay_in2_nopull: pinmux_cbb_relay_in2_nopull { ++ pinctrl-single,pins = < ++ 0x030 0x2f /* gpmc_ad12 - rx enabled | nopull | - MODE7 (GPIO1_12) */ ++ >; ++ }; ++ cbb_relay_in2_pullup: pinmux_cbb_relay_in2_pullup { ++ pinctrl-single,pins = < ++ 0x030 0x37 /* gpmc_ad12 - rx enabled | pullup | - MODE7 (GPIO1_12) */ ++ >; ++ }; ++ cbb_relay_in2_pulldown: pinmux_cbb_relay_in2_pulldown { ++ pinctrl-single,pins = < ++ 0x030 0x27 /* gpmc_ad12 - rx enabled | pulldown | - MODE7 (GPIO1_12) */ ++ >; ++ }; ++ ++ cbb_relay_in3_nopull: pinmux_cbb_relay_in3_nopull { ++ pinctrl-single,pins = < ++ 0x028 0x2f /* gpmc_ad10 - rx enabled | nopull | - MODE7 (GPIO0_26) */ ++ >; ++ }; ++ cbb_relay_in3_pullup: pinmux_cbb_relay_in3_pullup { ++ pinctrl-single,pins = < ++ 0x028 0x37 /* gpmc_ad10 - rx enabled | pullup | - MODE7 (GPIO0_26) */ ++ >; ++ }; ++ cbb_relay_in3_pulldown: pinmux_cbb_relay_in3_pulldown { ++ pinctrl-single,pins = < ++ 0x028 0x27 /* gpmc_ad10 - rx enabled | pulldown | - MODE7 (GPIO0_26) */ ++ >; ++ }; ++ ++ cbb_relay_in4_nopull: pinmux_cbb_relay_in4_nopull { ++ pinctrl-single,pins = < ++ 0x03c 0x2f /* gpmc_ad15 - rx enabled | nopull | - MODE7 (GPIO1_15) */ ++ >; ++ }; ++ cbb_relay_in4_pullup: pinmux_cbb_relay_in4_pullup { ++ pinctrl-single,pins = < ++ 0x03c 0x37 /* gpmc_ad15 - rx enabled | pullup | - MODE7 (GPIO1_15) */ ++ >; ++ }; ++ cbb_relay_in4_pulldown: pinmux_cbb_relay_in4_pulldown { ++ pinctrl-single,pins = < ++ 0x03c 0x27 /* gpmc_ad15 - rx enabled | pulldown | - MODE7 (GPIO1_15) */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ /* Sets pinmux for servo output. */ ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ cbb_relay_servo_pins: pinmux_cbb_relay_servo_pins { ++ pinctrl-single,pins = < ++ 0x048 0x6 /* gpmc_a2 - MODE 6 (EHRPWM1A) */ ++ >; ++ }; ++ }; ++ }; ++ ++ /*----- End pinmux -----*/ ++ ++ /*----- Start subsystem/module enable -----*/ ++ ++ fragment@4 { ++ /* Enable the enhanced resolution PWM 1 sub-system. */ ++ target = <&epwmss1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ /* Enable the enhanced resolution PWM 1 module. */ ++ target = <&ehrpwm1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ /*----- End subsystem/module enable -----*/ ++ ++ /*----- Start ocp driver setup -----*/ ++ ++ fragment@6 { ++ /* Enable pinmux-helper driver for setting input pull configuration. */ ++ target = <&ocp>; /* On-Chip Peripherals */ ++ __overlay__ { ++ CBB-Relay-out-pins { ++ compatible = "bone-pinmux-helper"; /* Use the pinmux helper */ ++ status="okay"; ++ /* Define custom names for indexes in pinctrl array: */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cbb_relay_out_pins>; ++ }; ++ }; ++ }; ++ ++ ++ fragment@7 { ++ /* Enable pinmux-helper driver for setting input pull configuration. */ ++ target = <&ocp>; /* On-Chip Peripherals */ ++ __overlay__ { ++ CBB-Relay-in1-pull { ++ compatible = "bone-pinmux-helper"; /* Use the pinmux helper */ ++ status="okay"; ++ /* Define custom names for indexes in pinctrl array: */ ++ pinctrl-names = "default", "pullup", "nopull"; ++ /* Set the elements of the pinctrl array to the pinmux overlays ++ defined above: */ ++ pinctrl-0 = <&cbb_relay_in1_pullup>; ++ pinctrl-1 = <&cbb_relay_in1_pullup>; ++ pinctrl-2 = <&cbb_relay_in1_nopull>; ++ }; ++ CBB-Relay-in2-pull { ++ compatible = "bone-pinmux-helper"; /* Use the pinmux helper */ ++ status="okay"; ++ pinctrl-names = "default", "pullup", "nopull"; ++ pinctrl-0 = <&cbb_relay_in2_pullup>; ++ pinctrl-1 = <&cbb_relay_in2_pullup>; ++ pinctrl-2 = <&cbb_relay_in2_nopull>; ++ }; ++ CBB-Relay-in3-pull { ++ compatible = "bone-pinmux-helper"; /* Use the pinmux helper */ ++ status="okay"; ++ pinctrl-names = "default", "pullup", "nopull"; ++ pinctrl-0 = <&cbb_relay_in3_pullup>; ++ pinctrl-1 = <&cbb_relay_in3_pullup>; ++ pinctrl-2 = <&cbb_relay_in3_nopull>; ++ }; ++ CBB-Relay-in4-pull { ++ compatible = "bone-pinmux-helper"; /* Use the pinmux helper */ ++ status="okay"; ++ pinctrl-names = "default", "pullup", "nopull"; ++ pinctrl-0 = <&cbb_relay_in4_pullup>; ++ pinctrl-1 = <&cbb_relay_in4_pullup>; ++ pinctrl-2 = <&cbb_relay_in4_nopull>; ++ }; ++ }; ++ }; ++ ++ ++ fragment@8 { ++ /* Enable the sysfs kernel driver to control ehrpwm1. */ ++ target = <&ocp>; ++ __overlay__ { ++ CBB-Relay-servo1 { ++ compatible = "pwm_test"; /* Use the pwm_test driver. */ ++ status = "okay"; ++ pwms = <&ehrpwm1 0 20000000 0>; ++ /* ehrpwm1 module, channel 0, 2e7 ns period (50Hz) normally low. */ ++ pwm-names = "Servo1"; /* Friendly name - this doesn't seem to be ++ implemented... */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&cbb_relay_servo_pins>; ++ enabled = <0>; /* Output disabled on boot. */ ++ duty = <1000000>; /* Initial pulse width = 5e5 ns = 0.5ms. */ ++ }; ++ }; ++ }; ++ ++ fragment@9 { ++ /* Enable ADC driver for analog inputs. */ ++ target = <&ocp>; ++ __overlay__ { ++ /* avoid stupid warning */ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ adc { ++ ti,adc-channels = <0 1 2 3 4 5 6 7>; ++ }; ++ }; ++ CBB-Relay-ain { ++ compatible = "bone-iio-helper"; ++ vsense-name = "AIN1", "AIN5"; ++ /* Set scale for voltages - values will be in mV (the CBB-Relay ++ has a /10 divider on AIN1): */ ++ vsense-scale = <1000 100>; ++ status = "okay"; ++ }; ++ }; ++ ++ /*----- End ocp driver setup -----*/ ++ ++ }; ++}; +-- +2.0.0.rc0 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0033-Firmware-Update-Replicape-device-tree-overlay-files-.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0033-Firmware-Update-Replicape-device-tree-overlay-files-.patch new file mode 100644 index 00000000..2de00c42 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0033-Firmware-Update-Replicape-device-tree-overlay-files-.patch @@ -0,0 +1,2012 @@ +From 0b9c69e4ca4a17f23f59931d7929c02cc6e7086c Mon Sep 17 00:00:00 2001 +From: Charles Steinkuehler +Date: Tue, 13 May 2014 21:13:00 +0000 +Subject: [PATCH 33/33] Firmware: Update Replicape device tree overlay files + Files from: https://bitbucket.org/intelligentagent/replicape + +Committed-by: Charles Steinkuehler +--- + firmware/Makefile | 7 +- + firmware/capes/BB-BONE-REPLICAP-00A1.dts | 233 ++++++++++++++++++++++ + firmware/capes/BB-BONE-REPLICAP-00A2.dts | 285 +++++++++++++++++++++++++++ + firmware/capes/BB-BONE-REPLICAP-00A3.dts | 291 ++++++++++++++++++++++++++++ + firmware/capes/BB-BONE-REPLICAP-00A4.dts | 288 +++++++++++++++++++++++++++ + firmware/capes/BB-BONE-REPLICAP-0A4A.dts | 288 +++++++++++++++++++++++++++ + firmware/capes/cape-bone-replicape-00A2.dts | 251 ------------------------ + firmware/capes/cape-bone-replicape-00A3.dts | 291 ---------------------------- + 8 files changed, 1390 insertions(+), 544 deletions(-) + create mode 100644 firmware/capes/BB-BONE-REPLICAP-00A1.dts + create mode 100644 firmware/capes/BB-BONE-REPLICAP-00A2.dts + create mode 100644 firmware/capes/BB-BONE-REPLICAP-00A3.dts + create mode 100644 firmware/capes/BB-BONE-REPLICAP-00A4.dts + create mode 100644 firmware/capes/BB-BONE-REPLICAP-0A4A.dts + delete mode 100644 firmware/capes/cape-bone-replicape-00A2.dts + delete mode 100644 firmware/capes/cape-bone-replicape-00A3.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index 90d4ad2..6e3f77a 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -196,8 +196,11 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + BB-BONE-BACONE-00A0.dtbo \ + BB-BONE-BACONE2-00A0.dtbo \ + DNIL-AMPCAPE-1-00R1.dtbo \ +- cape-bone-replicape-00A2.dtbo \ +- cape-bone-replicape-00A3.dtbo \ ++ BB-BONE-REPLICAP-00A1.dtbo \ ++ BB-BONE-REPLICAP-00A2.dtbo \ ++ BB-BONE-REPLICAP-00A3.dtbo \ ++ BB-BONE-REPLICAP-00A4.dtbo \ ++ BB-BONE-REPLICAP-0A4A.dtbo \ + cape-univ-emmc-00A0.dtbo \ + cape-universal-00A0.dtbo \ + cape-universaln-00A0.dtbo \ +diff --git a/firmware/capes/BB-BONE-REPLICAP-00A1.dts b/firmware/capes/BB-BONE-REPLICAP-00A1.dts +new file mode 100644 +index 0000000..4f2342e +--- /dev/null ++++ b/firmware/capes/BB-BONE-REPLICAP-00A1.dts +@@ -0,0 +1,233 @@ ++/* ++ * Copyright (C) 2013 Intelligent Agent AS ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-REPLICAP"; ++ version = "00A1"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ // From Cameon.net ++ // Bit 5: 1 - Input, 0 - Output ++ // Bit 4: 1 - Pull up, 0 - Pull down ++ // Bit 3: 1 - Pull disabled, 0 - Pull enabled ++ // Bit 2: - Mode ++ // Bit 1: - Mode ++ // Bit 0: - Mode ++ bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { ++ pinctrl-single,pins = < ++ 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ ++ 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ ++ 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ ++ 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ ++ 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ ++ >; ++ }; ++ pwm_mosfet_ext1_pins: pinmux_pwm_mosfet_ext1_pins { ++ pinctrl-single,pins = < ++ 0x024 0x4 /* P8_13 = gpmc_ad9 = ehrpwm2B = Heater_ext1 | MODE 4 */ ++ >; ++ }; ++ pwm_mosfet_ext2_pins: pinmux_pwm_mosfet_ext2_pins { ++ pinctrl-single,pins = < ++ 0x020 0x4 /* P8_19 = gpmc_ad8 = ehrpwm2A = Heater_ext2 | MODE 4 */ ++ >; ++ }; ++ pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ ++ pinctrl-single,pins = < ++ 0x018 0x07 /* P8_3 = DIR_EXT_2 = GPIO1_6 gpmc_ad6.gpio1[6] */ ++ 0x01C 0x07 /* P8_4 = DIR_EXT_1 = GPIO1_7 gpmc_ad7.gpio1[7] */ ++ 0x008 0x07 /* P8_5 = DIR_Z = GPIO1_2 gpmc_ad2.gpio1[2] */ ++ 0x034 0x07 /* P8_11 = DIR_X = GPIO1_13 gpmc_ad13.gpio1[13] */ ++ 0x030 0x07 /* P8_12 = STEP_X = GPIO1_12 gpmc_ad12.gpio1[12] */ ++ 0x038 0x07 /* P8_16 = STEP_EXT_2 = GPIO1_14 gpmc_ad14.gpio1[14] */ ++ 0x084 0x07 /* P8_20 = STEP_Y = GPIO1_31 gpmc_csn2.gpio1[31] */ ++ 0x080 0x07 /* P8_21 = DIR_Y = GPIO1_30 gpmc_csn1.gpio1[30] */ ++ 0x004 0x07 /* P8_24 = STEP_Z = GPIO1_1 gpmc_ad1 .gpio1[1] */ ++ 0x1AC 0x07 /* P9_25 = STEP_EXT_1 = GPIO3_21 mcasp0_ahclkx.gpio3[21] */ ++ >; ++ }; ++ ++ pwm_mosfet_hbp_pins: pinmux_pwm_mosfet_hbp_pins { ++ pinctrl-single,pins = < ++ 0x150 0x3 /* P9_14 = spi0_sclk = ehrpwm0A = Heater_HBP | MODE 3 */ ++ >; ++ }; ++ ++ pruicss_fault_pins: pinmux_pruicss_fault_pins{ ++ pinctrl-single,pins = < ++ 0x094 0x37 // P8_8 = FAULT_EXT_2 = GPIO2_2 gpmc_oen_ren.gpio2[3] ++ 0x098 0x37 // P8_10 = FAULT_X = GPIO2_4 gpmc_wen.gpio2[4] ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bone_replicape_spi1_pins>; ++ cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; ++ ++ stepper_control{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; // Stepper control has mode 1 (CPOL = 0, CPHA = 1) ++ }; ++ ++ stepper_current{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ // Stepper current has mode 0 (CPOL = 0, CPHA = 0) ++ }; ++ }; ++ }; ++ fragment@2 { ++ target = <&epwmss2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ehrpwm2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&epwmss0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&ehrpwm0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6{ ++ target = <&pruss>; ++ __overlay__{ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pruicss_stepper_pins>; ++ ++ stepper_x{ ++ pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; ++ gpios = <&gpio2 12 0 ++ &gpio2 13 0>; ++ }; ++ stepper_y{ ++ pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; ++ gpios =<&gpio2 31 0 ++ &gpio2 30 0>; ++ }; ++ stepper_z{ ++ pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; ++ gpios = <&gpio2 1 0 ++ &gpio2 2 0>; ++ }; ++ stepper_ext_1{ ++ pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; ++ gpios = <&gpio4 21 0 ++ &gpio2 7 0>; ++ }; ++ stepper_ext_2{ ++ pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; ++ gpios = <&gpio2 14 0 ++ &gpio2 6 0>; ++ }; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&ocp>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ mosfet_ext1 { ++ compatible = "pwm_test"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_mosfet_ext1_pins>; ++ pwms = <&ehrpwm2 1 500000 1>; ++ pwm-names = "Mosfet_Ext_1"; ++ enabled = <1>; ++ polarity = <1>; // 0 = normal, 1 = inverse ++ duty = <0>; ++ status = "okay"; ++ }; ++ mosfet_ext2 { ++ compatible = "pwm_test"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_mosfet_ext2_pins>; ++ pwms = <&ehrpwm2 0 500000 1>; ++ pwm-names = "Mosfet_Ext_2"; ++ enabled = <1>; ++ duty = <0>; ++ status = "okay"; ++ }; ++ mosfet_hbp { ++ compatible = "pwm_test"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_mosfet_hbp_pins>; ++ pwms = <&ehrpwm0 0 500000 1>; ++ pwm-names = "Mosfet_HBP"; ++ enabled = <1>; ++ duty = <0>; ++ status = "okay"; ++ }; ++ ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ tsc { ++ ti,wires = <4>; ++ }; ++ adc { ++ ti,adc-channels = <4>; ++ }; ++ }; ++ ++ thermistors{ ++ compatible = "bone-iio-helper"; ++ vsense-name = "AIN4", "AIN5", "AIN6", "AIN7"; ++ vsense-scale = <100 100 100 100 >; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++}; +diff --git a/firmware/capes/BB-BONE-REPLICAP-00A2.dts b/firmware/capes/BB-BONE-REPLICAP-00A2.dts +new file mode 100644 +index 0000000..84d33ed +--- /dev/null ++++ b/firmware/capes/BB-BONE-REPLICAP-00A2.dts +@@ -0,0 +1,285 @@ ++/* ++ * Copyright (C) 2013 Intelligent Agent AS ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-REPLICAP"; ++ version = "00A2"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header P8 uses */ ++ "P8.16", /* (3) DIR_EXT_2 */ ++ "P8.15", /* (4) DIR_EXT_1 */ ++ "P8.14", /* (5) DIR_Z */ ++ "P8.17", /* (6) STEP_X */ ++ "P8.7", /* END_STOP_Y1 */ ++ "P8.8", /* FAULT_EXT_2 */ ++ "P8.9", /* FAULT_Y */ ++ "P8.10", /* FAULT_x */ ++ "P8.18", /* FAULT_EXT_1 */ ++ "P8.11", /* (22) STEP_EXT_2 */ ++ "P8.12", /* (23) STEP_Y */ ++ "P8.13", /* (24) STEP_Z */ ++ "P8.19", /* (25) DIR_Y */ ++ "P8.26", /* DIR_X */ ++ /* the pin header P9 uses */ ++ "P9.11", /* END_STOP_Z1 */ ++ "P9.12", /* STEP_EXT_1 */ ++ "P9.13", /* END_STOP_X2 */ ++ "P9.18", /* END_STOP_Z2 */ ++ "P9.24", /* FAULT_Z */ ++ "P9.25", /* END_STOP_Y2 */ ++ "P9.26", /* END_STOP_X1 */ ++ "P9.28", /* SPI1_CS0 */ ++ "P9.29", /* SPI1_MISO */ ++ "P9.30", /* SPI1_MOSI */ ++ "P9.31", /* SPI1_SCLK */ ++ "P9.33", /* AIN4 */ ++ "P9.35", /* AIN6 */ ++ "P9.36", /* AIN5 */ ++ "P9.42", /* SPI1_CS1 */ ++ /* Hardware IP cores in use */ ++ "spi1", ++ "pruss"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { ++ pinctrl-single,pins = < ++ 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ ++ 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ ++ 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ ++ 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ ++ 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ ++ >; ++ }; ++ pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ ++ pinctrl-single,pins = < ++ 0x038 0x07 // P8_16 (3) = DIR_EXT_2 = GPIO1_14 ++ 0x03C 0x07 // P8_15 (4) = DIR_EXT_1 = GPIO1_15 ++ 0x028 0x07 // P8_14 (5) = DIR_Z = GPIO0_26 ++ 0x02C 0x07 // P8_17 (6) = STEP_X = GPIO0_27 ++ 0x034 0x07 // P8_11 (22) = step_ext_2 = GPIO1_13 ++ 0x030 0x07 // P8_12 (23) = Step_y = GPIO1_12 ++ 0x024 0x07 // P8_13 (24) = Step_z = GPIO0_23 ++ 0x020 0x07 // P8_19 (25) = Dir_y = GPIO0_22 ++ 0x07C 0x07 // P8_26 = Dir_x = GPIO1_29 ++ 0x078 0x07 // P9_12 = step ext 1 = GPIO1_28 ++ >; ++ }; ++ ++ stepper_fault_pins: pinmux_stepper_fault_pins{ ++ pinctrl-single,pins = < ++ 0x094 0x37 // P8_8 = Fault Ext 2 = GPIO2_2 gpmc_oen_ren.gpio2[3] ++ 0x09C 0x37 // P8_9 = FAYLT Y = GPIO2_5 ++ 0x098 0x37 // P8_10 = FAULT X = GPIO2_4 gpmc_wen.gpio2[4] ++ 0x08C 0x37 // P8_18 = Fault_ext 1 = GPIO2_1 ++ 0x184 0x37 // P9_24 = Fault Z = GPIO0_15 ++ >; ++ }; ++ ++ end_stop_pins: pinmux_end_stop_pins{ ++ pinctrl-single,pins = < ++ 0x090 0x37 // P8_7 = End stop X1 = GPIO2_2 ++ 0x070 0x37 // P9_11 = End stop Y1 = GPIO0_30 ++ 0x074 0x37 // P9_13 = End stop Z1 = GPIO0_31 ++ 0x158 0x37 // P9_18 = End stop Z2 = GPIO0_4 ++ 0x1AC 0x37 // P9_25 = End stop Y2 = GPIO3_21 ++ 0x180 0x37 // P9_26 = End stop X2 = GPIO0_14 ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bone_replicape_spi1_pins>; ++ cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; ++ ++ stepper_control{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ }; ++ ++ stepper_current{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++ }; ++ }; ++ ++ fragment@2{ ++ target = <&pruss>; ++ __overlay__{ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pruicss_stepper_pins>; ++ ++ stepper_x{ ++ pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; ++ gpios = <&gpio1 27 0 ++ &gpio2 29 0>; ++ }; ++ stepper_y{ ++ pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; ++ gpios =<&gpio2 12 0 ++ &gpio1 22 0>; ++ }; ++ stepper_z{ ++ pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; ++ gpios = <&gpio1 23 0 ++ &gpio1 26 0>; ++ }; ++ stepper_ext_1{ ++ pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; ++ gpios = <&gpio2 28 0 ++ &gpio2 15 0>; ++ }; ++ stepper_ext_2{ ++ pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; ++ gpios = <&gpio2 13 0 ++ &gpio2 14 0>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ocp>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ tsc { ++ ti,wires = <4>; ++ }; ++ adc { ++ ti,adc-channels = <4>; ++ }; ++ }; ++ ++ thermistors{ ++ compatible = "bone-iio-helper"; ++ vsense-name = "AIN4", "AIN5", "AIN6", "AIN7"; ++ vsense-scale = <100 100 100 100 >; ++ status = "okay"; ++ }; ++ gpio_keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&end_stop_pins>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch_x1 { ++ label = "End-stop-X1"; ++ debounce_interval = <50>; ++ linux,code = <1>; ++ gpios = <&gpio3 2 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_x2 { ++ label = "End-stop-X2"; ++ debounce_interval = <50>; ++ linux,code = <2>; ++ gpios = <&gpio1 14 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y1 { ++ label = "End-stop-Y1"; ++ debounce_interval = <50>; ++ linux,code = <3>; ++ gpios = <&gpio1 30 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y2 { ++ label = "End-stop-Y2"; ++ debounce_interval = <50>; ++ linux,code = <4>; ++ gpios = <&gpio4 21 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z1 { ++ label = "End-stop-Z1"; ++ debounce_interval = <50>; ++ linux,code = <5>; ++ gpios = <&gpio1 31 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z2 { ++ label = "End-stop-Z2"; ++ debounce_interval = <50>; ++ linux,code = <6>; ++ gpios = <&gpio1 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_x { ++ label = "Fault_X"; ++ debounce_interval = <50>; ++ linux,code = <7>; ++ gpios = <&gpio3 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_y { ++ label = "Fault_Y"; ++ debounce_interval = <50>; ++ linux,code = <8>; ++ gpios = <&gpio3 5 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_z { ++ label = "Fault_Z"; ++ debounce_interval = <50>; ++ linux,code = <9>; ++ gpios = <&gpio1 15 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext1 { ++ label = "Fault_Ext_1"; ++ debounce_interval = <50>; ++ linux,code = <10>; ++ gpios = <&gpio3 1 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext2 { ++ label = "Fault_Ext_2"; ++ debounce_interval = <50>; ++ linux,code = <11>; ++ gpios = <&gpio3 2 0x5>; ++ gpio-key,wakeup; ++ }; ++ ++ }; ++ }; ++ }; ++}; +diff --git a/firmware/capes/BB-BONE-REPLICAP-00A3.dts b/firmware/capes/BB-BONE-REPLICAP-00A3.dts +new file mode 100644 +index 0000000..8cb299f +--- /dev/null ++++ b/firmware/capes/BB-BONE-REPLICAP-00A3.dts +@@ -0,0 +1,291 @@ ++/* ++ * Copyright (C) 2013 Intelligent Agent AS ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-REPLICAP"; ++ version = "00A3"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header P8 uses */ ++ "P8.16", /* (3) DIR_EXT_2 */ ++ "P8.15", /* (4) DIR_EXT_1 */ ++ "P8.14", /* (5) DIR_Z */ ++ "P8.17", /* (6) STEP_X */ ++ "P8.7", /* END_STOP_Y1 */ ++ "P8.8", /* FAULT_EXT_2 */ ++ "P8.9", /* FAULT_Y */ ++ "P8.10", /* FAULT_x */ ++ "P8.18", /* FAULT_EXT_1 */ ++ "P8.11", /* (22) STEP_EXT_2 */ ++ "P8.12", /* (23) STEP_Y */ ++ "P8.13", /* (24) STEP_Z */ ++ "P8.19", /* (25) DIR_Y */ ++ "P8.26", /* DIR_X */ ++ /* the pin header P9 uses */ ++ "P9.11", /* END_STOP_Z1 */ ++ "P9.12", /* STEP_EXT_1 */ ++ "P9.13", /* END_STOP_X2 */ ++ "P9.18", /* END_STOP_Z2 */ ++ "P9.22", /* Dallas 1W */ ++ "P9.24", /* FAULT_Z */ ++ "P9.25", /* END_STOP_Y2 */ ++ "P9.26", /* END_STOP_X1 */ ++ "P9.28", /* SPI1_CS0 */ ++ "P9.29", /* SPI1_MISO */ ++ "P9.30", /* SPI1_MOSI */ ++ "P9.31", /* SPI1_SCLK */ ++ "P9.33", /* AIN4 */ ++ "P9.35", /* AIN6 */ ++ "P9.36", /* AIN5 */ ++ "P9.42", /* SPI1_CS1 */ ++ /* Hardware IP cores in use */ ++ "spi1", ++ "pruss"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { ++ pinctrl-single,pins = < ++ 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ ++ 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ ++ 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ ++ 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ ++ 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ ++ >; ++ }; ++ pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ ++ pinctrl-single,pins = < ++ 0x038 0x07 // P8_16 (3) = DIR_EXT_2 = GPIO1_14 ++ 0x03C 0x07 // P8_15 (4) = DIR_EXT_1 = GPIO1_15 ++ 0x028 0x07 // P8_14 (5) = DIR_Z = GPIO0_26 ++ 0x02C 0x07 // P8_17 (6) = STEP_X = GPIO0_27 ++ 0x034 0x07 // P8_11 (22) = step_ext_2 = GPIO1_13 ++ 0x030 0x07 // P8_12 (23) = Step_y = GPIO1_12 ++ 0x024 0x07 // P8_13 (24) = Step_z = GPIO0_23 ++ 0x020 0x07 // P8_19 (25) = Dir_y = GPIO0_22 ++ 0x07C 0x07 // P8_26 = Dir_x = GPIO1_29 ++ 0x078 0x07 // P9_12 = step ext 1 = GPIO1_28 ++ >; ++ }; ++ ++ stepper_fault_pins: pinmux_stepper_fault_pins{ ++ pinctrl-single,pins = < ++ 0x094 0x37 // P8_8 = Fault Ext 2 = GPIO2_3 gpmc_oen_ren.gpio2[3] ++ 0x09C 0x37 // P8_9 = FAYLT Y = GPIO2_5 ++ 0x098 0x37 // P8_10 = FAULT X = GPIO2_4 gpmc_wen.gpio2[4] ++ 0x08C 0x37 // P8_18 = Fault_ext 1 = GPIO2_1 ++ 0x184 0x37 // P9_24 = Fault Z = GPIO0_15 ++ >; ++ }; ++ ++ end_stop_pins: pinmux_end_stop_pins{ ++ pinctrl-single,pins = < ++ 0x090 0x37 // P8_7 = End stop X1 = GPIO2_2 ++ 0x070 0x37 // P9_11 = End stop Y1 = GPIO0_30 ++ 0x074 0x37 // P9_13 = End stop Z1 = GPIO0_31 ++ 0x158 0x37 // P9_18 = End stop Z2 = GPIO0_4 ++ 0x1AC 0x37 // P9_25 = End stop Y2 = GPIO3_21 ++ 0x180 0x37 // P9_26 = End stop X2 = GPIO0_14 ++ >; ++ }; ++ dallas_w1_pins: pinmux_dallas_w1_pins { ++ pinctrl-single,pins = < ++ 0x150 0x37 // Dallas 1W ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bone_replicape_spi1_pins>; ++ cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; ++ ++ stepper_control{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; // Stepper control has mode 1 (CPOL = 0, CPHA = 1) ++ }; ++ ++ stepper_current{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ // Stepper current has mode 0 (CPOL = 0, CPHA = 0) ++ }; ++ }; ++ }; ++ ++ fragment@2{ ++ target = <&pruss>; ++ __overlay__{ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pruicss_stepper_pins>; ++ ++ stepper_x{ ++ pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; ++ gpios = <&gpio1 27 0 ++ &gpio2 29 0>; ++ }; ++ stepper_y{ ++ pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; ++ gpios =<&gpio2 12 0 ++ &gpio1 22 0>; ++ }; ++ stepper_z{ ++ pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; ++ gpios = <&gpio1 23 0 ++ &gpio1 26 0>; ++ }; ++ stepper_ext_1{ ++ pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; ++ gpios = <&gpio2 28 0 ++ &gpio2 15 0>; ++ }; ++ stepper_ext_2{ ++ pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; ++ gpios = <&gpio2 13 0 ++ &gpio2 14 0>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ocp>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ adc { ++ ti,adc-channels = <4 5 6 7>; ++ }; ++ }; ++ ++ gpio_keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&end_stop_pins>; ++ pinctrl-1 = <&stepper_fault_pins>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch_x1 { ++ label = "End-stop-X1"; ++ debounce_interval = <50>; ++ linux,code = <1>; ++ gpios = <&gpio3 2 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_x2 { ++ label = "End-stop-X2"; ++ debounce_interval = <50>; ++ linux,code = <2>; ++ gpios = <&gpio1 14 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y1 { ++ label = "End-stop-Y1"; ++ debounce_interval = <50>; ++ linux,code = <3>; ++ gpios = <&gpio1 30 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y2 { ++ label = "End-stop-Y2"; ++ debounce_interval = <50>; ++ linux,code = <4>; ++ gpios = <&gpio4 21 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z1 { ++ label = "End-stop-Z1"; ++ debounce_interval = <50>; ++ linux,code = <5>; ++ gpios = <&gpio1 31 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z2 { ++ label = "End-stop-Z2"; ++ debounce_interval = <50>; ++ linux,code = <6>; ++ gpios = <&gpio1 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_x { ++ label = "Fault-X"; ++ debounce_interval = <50>; ++ linux,code = <7>; ++ gpios = <&gpio3 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_y { ++ label = "Fault-Y"; ++ debounce_interval = <50>; ++ linux,code = <8>; ++ gpios = <&gpio3 5 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_z { ++ label = "Fault-Z"; ++ debounce_interval = <50>; ++ linux,code = <9>; ++ gpios = <&gpio1 15 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext_1 { ++ label = "Fault-Ext-1"; ++ debounce_interval = <50>; ++ linux,code = <10>; ++ gpios = <&gpio3 1 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext_2 { ++ label = "Fault-Ext-2"; ++ debounce_interval = <50>; ++ linux,code = <11>; ++ gpios = <&gpio3 3 0x5>; ++ gpio-key,wakeup; ++ }; ++ }; ++ onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dallas_w1_pins>; ++ status = "okay"; ++ gpios = <&gpio1 2 0>; ++ }; ++ }; ++ }; ++}; +diff --git a/firmware/capes/BB-BONE-REPLICAP-00A4.dts b/firmware/capes/BB-BONE-REPLICAP-00A4.dts +new file mode 100644 +index 0000000..1d07e46 +--- /dev/null ++++ b/firmware/capes/BB-BONE-REPLICAP-00A4.dts +@@ -0,0 +1,288 @@ ++/* ++ * Copyright (C) 2013 Intelligent Agent AS ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-REPLICAP"; ++ version = "00A4"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header P8 uses */ ++ "P8.8", /* FAULT_EXT_2 */ ++ "P8.9", /* FAULT_Y */ ++ "P8.10", /* FAULT_X */ ++ "P8.11", /* STEP_EXT_2 */ ++ "P8.12", /* STEP_Y */ ++ "P8.13", /* STEP_Z */ ++ "P8.14", /* DIR_Z */ ++ "P8.15", /* DIR_EXT_1 */ ++ "P8.16", /* DIR_EXT_2 */ ++ "P8.17", /* STEP_X */ ++ "P8.18", /* FAULT_EXT_1 */ ++ "P8.19", /* DIR_Y */ ++ "P8.26", /* DIR_X */ ++ /* the pin header P9 uses */ ++ "P9.11", /* END_STOP_X2 */ ++ "P9.12", /* STEP_EXT_1 */ ++ "P9.13", /* END_STOP_Z1 */ ++ "P9.16", /* END_STOP_Y2 */ ++ "P9.18", /* END_STOP_Z2 */ ++ "P9.22", /* Dallas 1W */ ++ "P9.23", /* END_STOP_Y1 */ ++ "P9.24", /* FAULT_Z */ ++ "P9.25", /* END_STOP_X1 */ ++ "P9.28", /* SPI1_CS0 */ ++ "P9.29", /* SPI1_MISO */ ++ "P9.30", /* SPI1_MOSI */ ++ "P9.31", /* SPI1_SCLK */ ++ "P9.33", /* AIN4 */ ++ "P9.35", /* AIN6 */ ++ "P9.36", /* AIN5 */ ++ "P9.42"; /* SPI1_CS1 */ ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { ++ pinctrl-single,pins = < ++ 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ ++ 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ ++ 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ ++ 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ ++ 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ ++ >; ++ }; ++ pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ ++ pinctrl-single,pins = < ++ 0x038 0x07 // P8_16 (3) = DIR_EXT_2 = GPIO1_14 ++ 0x03C 0x07 // P8_15 (4) = DIR_EXT_1 = GPIO1_15 ++ 0x028 0x07 // P8_14 (5) = DIR_Z = GPIO0_26 ++ 0x02C 0x07 // P8_17 (6) = STEP_X = GPIO0_27 ++ 0x034 0x07 // P8_11 (22) = step_ext_2 = GPIO1_13 ++ 0x030 0x07 // P8_12 (23) = Step_y = GPIO1_12 ++ 0x024 0x07 // P8_13 (24) = Step_z = GPIO0_23 ++ 0x020 0x07 // P8_19 (25) = Dir_y = GPIO0_22 ++ 0x07C 0x07 // P8_26 = Dir_x = GPIO1_29 ++ 0x078 0x07 // P9_12 = step ext 1 = GPIO1_28 ++ >; ++ }; ++ ++ stepper_fault_pins: pinmux_stepper_fault_pins{ ++ pinctrl-single,pins = < ++ 0x094 0x37 // P8_8 = Fault Ext 2 = GPIO2_3 gpmc_oen_ren.gpio2[3] ++ 0x09C 0x37 // P8_9 = FAYLT Y = GPIO2_5 ++ 0x098 0x37 // P8_10 = FAULT X = GPIO2_4 gpmc_wen.gpio2[4] ++ 0x08C 0x37 // P8_18 = Fault_ext 1 = GPIO2_1 ++ 0x184 0x37 // P9_24 = Fault Z = GPIO0_15 ++ >; ++ }; ++ ++ end_stop_pins: pinmux_end_stop_pins{ ++ pinctrl-single,pins = < ++ 0x1AC 0x37 // P9_25 = End stop X1 = GPIO3_21 ++ 0x070 0x37 // P9_11 = End stop X2 = GPIO0_30 ++ 0x044 0x37 // P9_23 = End stop Y1 = GPIO1_17 ++ 0x04C 0x37 // P9_16 = End stop Y2 = GPIO1_19 ++ 0x074 0x37 // P9_13 = End stop Z1 = GPIO0_31 ++ 0x158 0x37 // P9_18 = End stop Z2 = GPIO0_4 ++ >; ++ }; ++ dallas_w1_pins: pinmux_dallas_w1_pins { ++ pinctrl-single,pins = < ++ 0x150 0x37 // Dallas 1W ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bone_replicape_spi1_pins>; ++ cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; ++ ++ stepper_control{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; // Stepper control has mode 1 (CPOL = 0, CPHA = 1) ++ }; ++ ++ stepper_current{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ // Stepper current has mode 0 (CPOL = 0, CPHA = 0) ++ }; ++ }; ++ }; ++ ++ fragment@2{ ++ target = <&pruss>; ++ __overlay__{ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pruicss_stepper_pins>; ++ ++ stepper_x{ ++ pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; ++ gpios = <&gpio1 27 0 ++ &gpio2 29 0>; ++ }; ++ stepper_y{ ++ pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; ++ gpios =<&gpio2 12 0 ++ &gpio1 22 0>; ++ }; ++ stepper_z{ ++ pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; ++ gpios = <&gpio1 23 0 ++ &gpio1 26 0>; ++ }; ++ stepper_ext_1{ ++ pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; ++ gpios = <&gpio2 28 0 ++ &gpio2 15 0>; ++ }; ++ stepper_ext_2{ ++ pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; ++ gpios = <&gpio2 13 0 ++ &gpio2 14 0>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ocp>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ adc { ++ ti,adc-channels = <4 5 6 7>; ++ }; ++ }; ++ ++ gpio_keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&end_stop_pins>; ++ pinctrl-1 = <&stepper_fault_pins>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch_x1 { ++ label = "End-stop-X1"; ++ debounce_interval = <50>; ++ linux,code = <112>; ++ gpios = <&gpio4 21 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_x2 { ++ label = "End-stop-X2"; ++ debounce_interval = <50>; ++ linux,code = <113>; ++ gpios = <&gpio1 30 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y1 { ++ label = "End-stop-Y1"; ++ debounce_interval = <50>; ++ linux,code = <114>; ++ gpios = <&gpio2 17 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y2 { ++ label = "End-stop-Y2"; ++ debounce_interval = <50>; ++ linux,code = <115>; ++ gpios = <&gpio2 19 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z1 { ++ label = "End-stop-Z1"; ++ debounce_interval = <50>; ++ linux,code = <116>; ++ gpios = <&gpio1 31 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z2 { ++ label = "End-stop-Z2"; ++ debounce_interval = <50>; ++ linux,code = <117>; ++ gpios = <&gpio1 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_x { ++ label = "Fault-X"; ++ debounce_interval = <50>; ++ linux,code = <90>; ++ gpios = <&gpio3 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_y { ++ label = "Fault-Y"; ++ debounce_interval = <50>; ++ linux,code = <91>; ++ gpios = <&gpio3 5 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_z { ++ label = "Fault-Z"; ++ debounce_interval = <50>; ++ linux,code = <92>; ++ gpios = <&gpio1 15 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext_1 { ++ label = "Fault-Ext-1"; ++ debounce_interval = <50>; ++ linux,code = <93>; ++ gpios = <&gpio3 1 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext_2 { ++ label = "Fault-Ext-2"; ++ debounce_interval = <50>; ++ linux,code = <94>; ++ gpios = <&gpio3 3 0x5>; ++ gpio-key,wakeup; ++ }; ++ }; ++ onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dallas_w1_pins>; ++ status = "okay"; ++ gpios = <&gpio1 2 0>; ++ }; ++ }; ++ }; ++}; +diff --git a/firmware/capes/BB-BONE-REPLICAP-0A4A.dts b/firmware/capes/BB-BONE-REPLICAP-0A4A.dts +new file mode 100644 +index 0000000..3becb9c +--- /dev/null ++++ b/firmware/capes/BB-BONE-REPLICAP-0A4A.dts +@@ -0,0 +1,288 @@ ++/* ++ * Copyright (C) 2013 Intelligent Agent AS ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-REPLICAP"; ++ version = "0A4A"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header P8 uses */ ++ "P8.8", /* FAULT_EXT_2 */ ++ "P8.9", /* FAULT_Y */ ++ "P8.10", /* FAULT_X */ ++ "P8.11", /* STEP_EXT_2 */ ++ "P8.12", /* STEP_Y */ ++ "P8.13", /* STEP_Z */ ++ "P8.14", /* DIR_Z */ ++ "P8.15", /* DIR_EXT_1 */ ++ "P8.16", /* DIR_EXT_2 */ ++ "P8.17", /* STEP_X */ ++ "P8.18", /* FAULT_EXT_1 */ ++ "P8.19", /* DIR_Y */ ++ "P8.26", /* DIR_X */ ++ /* the pin header P9 uses */ ++ "P9.11", /* END_STOP_X2 */ ++ "P9.12", /* STEP_EXT_1 */ ++ "P9.13", /* END_STOP_Z1 */ ++ "P9.16", /* END_STOP_Y2 */ ++ "P9.18", /* END_STOP_Z2 */ ++ "P9.22", /* Dallas 1W */ ++ "P9.23", /* END_STOP_Y1 */ ++ "P9.24", /* FAULT_Z */ ++ "P9.25", /* END_STOP_X1 */ ++ "P9.28", /* SPI1_CS0 */ ++ "P9.29", /* SPI1_MISO */ ++ "P9.30", /* SPI1_MOSI */ ++ "P9.31", /* SPI1_SCLK */ ++ "P9.33", /* AIN4 */ ++ "P9.35", /* AIN6 */ ++ "P9.36", /* AIN5 */ ++ "P9.42"; /* SPI1_CS1 */ ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { ++ pinctrl-single,pins = < ++ 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ ++ 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ ++ 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ ++ 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ ++ 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ ++ >; ++ }; ++ pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ ++ pinctrl-single,pins = < ++ 0x038 0x07 // P8_16 (3) = DIR_EXT_2 = GPIO1_14 ++ 0x03C 0x07 // P8_15 (4) = DIR_EXT_1 = GPIO1_15 ++ 0x028 0x07 // P8_14 (5) = DIR_Z = GPIO0_26 ++ 0x02C 0x07 // P8_17 (6) = STEP_X = GPIO0_27 ++ 0x034 0x07 // P8_11 (22) = step_ext_2 = GPIO1_13 ++ 0x030 0x07 // P8_12 (23) = Step_y = GPIO1_12 ++ 0x024 0x07 // P8_13 (24) = Step_z = GPIO0_23 ++ 0x020 0x07 // P8_19 (25) = Dir_y = GPIO0_22 ++ 0x07C 0x07 // P8_26 = Dir_x = GPIO1_29 ++ 0x078 0x07 // P9_12 = step ext 1 = GPIO1_28 ++ >; ++ }; ++ ++ stepper_fault_pins: pinmux_stepper_fault_pins{ ++ pinctrl-single,pins = < ++ 0x094 0x37 // P8_8 = Fault Ext 2 = GPIO2_3 gpmc_oen_ren.gpio2[3] ++ 0x09C 0x37 // P8_9 = FAYLT Y = GPIO2_5 ++ 0x098 0x37 // P8_10 = FAULT X = GPIO2_4 gpmc_wen.gpio2[4] ++ 0x08C 0x37 // P8_18 = Fault_ext 1 = GPIO2_1 ++ 0x184 0x37 // P9_24 = Fault Z = GPIO0_15 ++ >; ++ }; ++ ++ end_stop_pins: pinmux_end_stop_pins{ ++ pinctrl-single,pins = < ++ 0x1AC 0x37 // P9_25 = End stop X1 = GPIO3_21 ++ 0x070 0x37 // P9_11 = End stop X2 = GPIO0_30 ++ 0x044 0x37 // P9_23 = End stop Y1 = GPIO1_17 ++ 0x04C 0x37 // P9_16 = End stop Y2 = GPIO1_19 ++ 0x074 0x37 // P9_13 = End stop Z1 = GPIO0_31 ++ 0x158 0x37 // P9_18 = End stop Z2 = GPIO0_4 ++ >; ++ }; ++ dallas_w1_pins: pinmux_dallas_w1_pins { ++ pinctrl-single,pins = < ++ 0x150 0x37 // Dallas 1W ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bone_replicape_spi1_pins>; ++ cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; ++ ++ stepper_control{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; // Stepper control has mode 1 (CPOL = 0, CPHA = 1) ++ }; ++ ++ stepper_current{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ // Stepper current has mode 0 (CPOL = 0, CPHA = 0) ++ }; ++ }; ++ }; ++ ++ fragment@2{ ++ target = <&pruss>; ++ __overlay__{ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pruicss_stepper_pins>; ++ ++ stepper_x{ ++ pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; ++ gpios = <&gpio1 27 0 ++ &gpio2 29 0>; ++ }; ++ stepper_y{ ++ pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; ++ gpios =<&gpio2 12 0 ++ &gpio1 22 0>; ++ }; ++ stepper_z{ ++ pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; ++ gpios = <&gpio1 23 0 ++ &gpio1 26 0>; ++ }; ++ stepper_ext_1{ ++ pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; ++ gpios = <&gpio2 28 0 ++ &gpio2 15 0>; ++ }; ++ stepper_ext_2{ ++ pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; ++ gpios = <&gpio2 13 0 ++ &gpio2 14 0>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ocp>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ adc { ++ ti,adc-channels = <4 5 6 7>; ++ }; ++ }; ++ ++ gpio_keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&end_stop_pins>; ++ pinctrl-1 = <&stepper_fault_pins>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch_x1 { ++ label = "End-stop-X1"; ++ debounce_interval = <50>; ++ linux,code = <112>; ++ gpios = <&gpio4 21 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_x2 { ++ label = "End-stop-X2"; ++ debounce_interval = <50>; ++ linux,code = <113>; ++ gpios = <&gpio1 30 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y1 { ++ label = "End-stop-Y1"; ++ debounce_interval = <50>; ++ linux,code = <114>; ++ gpios = <&gpio2 17 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_y2 { ++ label = "End-stop-Y2"; ++ debounce_interval = <50>; ++ linux,code = <115>; ++ gpios = <&gpio2 19 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z1 { ++ label = "End-stop-Z1"; ++ debounce_interval = <50>; ++ linux,code = <116>; ++ gpios = <&gpio1 31 0x5>; ++ gpio-key,wakeup; ++ }; ++ switch_z2 { ++ label = "End-stop-Z2"; ++ debounce_interval = <50>; ++ linux,code = <117>; ++ gpios = <&gpio1 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_x { ++ label = "Fault-X"; ++ debounce_interval = <50>; ++ linux,code = <90>; ++ gpios = <&gpio3 4 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_y { ++ label = "Fault-Y"; ++ debounce_interval = <50>; ++ linux,code = <91>; ++ gpios = <&gpio3 5 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_z { ++ label = "Fault-Z"; ++ debounce_interval = <50>; ++ linux,code = <92>; ++ gpios = <&gpio1 15 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext_1 { ++ label = "Fault-Ext-1"; ++ debounce_interval = <50>; ++ linux,code = <93>; ++ gpios = <&gpio3 1 0x5>; ++ gpio-key,wakeup; ++ }; ++ fault_ext_2 { ++ label = "Fault-Ext-2"; ++ debounce_interval = <50>; ++ linux,code = <94>; ++ gpios = <&gpio3 3 0x5>; ++ gpio-key,wakeup; ++ }; ++ }; ++ onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dallas_w1_pins>; ++ status = "okay"; ++ gpios = <&gpio1 2 0>; ++ }; ++ }; ++ }; ++}; +diff --git a/firmware/capes/cape-bone-replicape-00A2.dts b/firmware/capes/cape-bone-replicape-00A2.dts +deleted file mode 100644 +index 1c023f3..0000000 +--- git/firmware/capes/cape-bone-replicape-00A2.dts 2014-08-26 21:25:36.131594915 +0200 ++++ /dev/null 2014-08-26 18:42:22.743307348 +0200 +@@ -1,251 +0,0 @@ +-/* +- * Copyright (C) 2013 Intelligent Agent AS +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +-/dts-v1/; +-/plugin/; +- +-/ { +- compatible = "ti,beaglebone", "ti,beaglebone-black"; +- +- /* identification */ +- part-number = "BB-BONE-REPLICAP"; +- version = "00A2"; +- +- /* state the resources this cape uses */ +- exclusive-use = +- /* the pin header P8 uses */ +- "P8.16", /* (3) DIR_EXT_2 */ +- "P8.15", /* (4) DIR_EXT_1 */ +- "P8.14", /* (5) DIR_Z */ +- "P8.17", /* (6) STEP_X */ +- "P8.7", /* END_STOP_Y1 */ +- "P8.8", /* FAULT_EXT_2 */ +- "P8.9", /* FAULT_Y */ +- "P8.10", /* FAULT_x */ +- "P8.18", /* FAULT_EXT_1 */ +- "P8.11", /* (22) STEP_EXT_2 */ +- "P8.12", /* (23) STEP_Y */ +- "P8.13", /* (24) STEP_Z */ +- "P8.19", /* (25) DIR_Y */ +- "P8.26", /* DIR_X */ +- /* the pin header P9 uses */ +- "P9.11", /* END_STOP_Z1 */ +- "P9.12", /* STEP_EXT_1 */ +- "P9.13", /* END_STOP_X2 */ +- "P9.18", /* END_STOP_Z2 */ +- "P9.24", /* FAULT_Z */ +- "P9.25", /* END_STOP_Y2 */ +- "P9.26", /* END_STOP_X1 */ +- "P9.28", /* SPI1_CS0 */ +- "P9.29", /* SPI1_MISO */ +- "P9.30", /* SPI1_MOSI */ +- "P9.31", /* SPI1_SCLK */ +- "P9.33", /* AIN4 */ +- "P9.35", /* AIN6 */ +- "P9.36", /* AIN5 */ +- "P9.42", /* SPI1_CS1 */ +- /* Hardware IP cores in use */ +- "spi1", +- "pruss"; +- +- fragment@0 { +- target = <&am33xx_pinmux>; +- __overlay__ { +- bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { +- pinctrl-single,pins = < +- 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ +- 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ +- 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ +- 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ +- 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ +- >; +- }; +- pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ +- pinctrl-single,pins = < +- 0x038 0x07 // P8_16 (3) = DIR_EXT_2 = GPIO1_14 +- 0x03C 0x07 // P8_15 (4) = DIR_EXT_1 = GPIO1_15 +- 0x028 0x07 // P8_14 (5) = DIR_Z = GPIO0_26 +- 0x02C 0x07 // P8_17 (6) = STEP_X = GPIO0_27 +- 0x034 0x07 // P8_11 (22) = step_ext_2 = GPIO1_13 +- 0x030 0x07 // P8_12 (23) = Step_y = GPIO1_12 +- 0x024 0x07 // P8_13 (24) = Step_z = GPIO0_23 +- 0x020 0x07 // P8_19 (25) = Dir_y = GPIO0_22 +- 0x07C 0x07 // P8_26 = Dir_x = GPIO1_29 +- 0x078 0x07 // P9_12 = step ext 1 = GPIO1_28 +- >; +- }; +- +- stepper_fault_pins: pinmux_stepper_fault_pins{ +- pinctrl-single,pins = < +- 0x094 0x37 // P8_8 = Fault Ext 2 = GPIO2_2 gpmc_oen_ren.gpio2[3] +- 0x09C 0x37 // P8_9 = FAYLT Y = GPIO2_5 +- 0x098 0x37 // P8_10 = FAULT X = GPIO2_4 gpmc_wen.gpio2[4] +- 0x08C 0x37 // P8_18 = Fault_ext 1 = GPIO2_1 +- 0x184 0x37 // P9_24 = Fault Z = GPIO0_15 +- >; +- }; +- +- end_stop_pins: pinmux_end_stop_pins{ +- pinctrl-single,pins = < +- 0x090 0x37 // P8_7 = End stop X1 = GPIO2_2 +- 0x070 0x37 // P9_11 = End stop Y1 = GPIO0_30 +- 0x074 0x37 // P9_13 = End stop Z1 = GPIO0_31 +- 0x158 0x37 // P9_18 = End stop Z2 = GPIO0_4 +- 0x1AC 0x37 // P9_25 = End stop Y2 = GPIO3_21 +- 0x180 0x37 // P9_26 = End stop X2 = GPIO0_14 +- >; +- }; +- }; +- }; +- +- fragment@1 { +- target = <&spi1>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; +- pinctrl-names = "default"; +- pinctrl-0 = <&bone_replicape_spi1_pins>; +- cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; +- +- stepper_control{ +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "spidev"; +- reg = <0>; +- spi-max-frequency = <16000000>; +- spi-cpha; // Stepper control has mode 1 (CPOL = 0, CPHA = 1) +- }; +- +- stepper_current{ +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "spidev"; +- reg = <1>; +- spi-max-frequency = <16000000>; +- // Stepper current has mode 0 (CPOL = 0, CPHA = 0) +- }; +- }; +- }; +- +- fragment@2{ +- target = <&pruss>; +- __overlay__{ +- status = "okay"; +- pinctrl-names = "default"; +- pinctrl-0 = <&pruicss_stepper_pins>; +- +- stepper_x{ +- pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; +- gpios = <&gpio1 27 0 +- &gpio2 29 0>; +- }; +- stepper_y{ +- pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; +- gpios =<&gpio2 12 0 +- &gpio1 22 0>; +- }; +- stepper_z{ +- pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; +- gpios = <&gpio1 23 0 +- &gpio1 26 0>; +- }; +- stepper_ext_1{ +- pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; +- gpios = <&gpio2 28 0 +- &gpio2 15 0>; +- }; +- stepper_ext_2{ +- pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; +- gpios = <&gpio2 13 0 +- &gpio2 14 0>; +- }; +- }; +- }; +- +- fragment@3 { +- target = <&ocp>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <1>; +- +- tscadc { +- compatible = "ti,ti-tscadc"; +- reg = <0x44e0d000 0x1000>; +- +- interrupt-parent = <&intc>; +- interrupts = <16>; +- ti,hwmods = "adc_tsc"; +- status = "okay"; +- +- tsc { +- ti,wires = <4>; +- }; +- adc { +- ti,adc-channels = <4>; +- }; +- }; +- +- thermistors{ +- compatible = "bone-iio-helper"; +- vsense-name = "AIN4", "AIN5", "AIN6", "AIN7"; +- vsense-scale = <100 100 100 100 >; +- status = "okay"; +- }; +- gpio_keys { +- compatible = "gpio-keys"; +- pinctrl-names = "default"; +- pinctrl-0 = <&end_stop_pins>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- switch_x1 { +- label = "End-stop-X1"; +- debounce_interval = <50>; +- linux,code = <1>; +- gpios = <&gpio3 2 0x5>; +- gpio-key,wakeup; +- }; +- switch_x2 { +- label = "End-stop-X2"; +- debounce_interval = <50>; +- linux,code = <2>; +- gpios = <&gpio1 14 0x5>; +- gpio-key,wakeup; +- }; +- switch_y1 { +- label = "End-stop-Y1"; +- debounce_interval = <50>; +- linux,code = <3>; +- gpios = <&gpio1 30 0x5>; +- gpio-key,wakeup; +- }; +- switch_y2 { +- label = "End-stop-Y2"; +- debounce_interval = <50>; +- linux,code = <4>; +- gpios = <&gpio4 21 0x5>; +- gpio-key,wakeup; +- }; +- switch_z1 { +- label = "End-stop-Z1"; +- debounce_interval = <50>; +- linux,code = <5>; +- gpios = <&gpio1 31 0x5>; +- gpio-key,wakeup; +- }; +- switch_z2 { +- label = "End-stop-Z2"; +- debounce_interval = <50>; +- linux,code = <6>; +- gpios = <&gpio1 4 0x5>; +- gpio-key,wakeup; +- }; +- }; +- }; +- }; +-}; +--- git/firmware/capes/cape-bone-replicape-00A3.dts 2014-08-26 21:25:36.267594918 +0200 ++++ /dev/null 2014-08-26 18:42:22.743307348 +0200 +@@ -1,291 +0,0 @@ +-/* +- * Copyright (C) 2013 Intelligent Agent AS +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +-/dts-v1/; +-/plugin/; +- +-/ { +- compatible = "ti,beaglebone", "ti,beaglebone-black"; +- +- /* identification */ +- part-number = "BB-BONE-REPLICAP"; +- version = "00A3"; +- +- /* state the resources this cape uses */ +- exclusive-use = +- /* the pin header P8 uses */ +- "P8.16", /* (3) DIR_EXT_2 */ +- "P8.15", /* (4) DIR_EXT_1 */ +- "P8.14", /* (5) DIR_Z */ +- "P8.17", /* (6) STEP_X */ +- "P8.7", /* END_STOP_Y1 */ +- "P8.8", /* FAULT_EXT_2 */ +- "P8.9", /* FAULT_Y */ +- "P8.10", /* FAULT_x */ +- "P8.18", /* FAULT_EXT_1 */ +- "P8.11", /* (22) STEP_EXT_2 */ +- "P8.12", /* (23) STEP_Y */ +- "P8.13", /* (24) STEP_Z */ +- "P8.19", /* (25) DIR_Y */ +- "P8.26", /* DIR_X */ +- /* the pin header P9 uses */ +- "P9.11", /* END_STOP_Z1 */ +- "P9.12", /* STEP_EXT_1 */ +- "P9.13", /* END_STOP_X2 */ +- "P9.18", /* END_STOP_Z2 */ +- "P9.22", /* Dallas 1W */ +- "P9.24", /* FAULT_Z */ +- "P9.25", /* END_STOP_Y2 */ +- "P9.26", /* END_STOP_X1 */ +- "P9.28", /* SPI1_CS0 */ +- "P9.29", /* SPI1_MISO */ +- "P9.30", /* SPI1_MOSI */ +- "P9.31", /* SPI1_SCLK */ +- "P9.33", /* AIN4 */ +- "P9.35", /* AIN6 */ +- "P9.36", /* AIN5 */ +- "P9.42", /* SPI1_CS1 */ +- /* Hardware IP cores in use */ +- "spi1", +- "pruss"; +- +- fragment@0 { +- target = <&am33xx_pinmux>; +- __overlay__ { +- bone_replicape_spi1_pins: pinmux_replicape_spi1_pins { +- pinctrl-single,pins = < +- 0x190 0x13 /* P9_31 = mcasp0_aclkx.spi1_sclk , OUTPUT_PULLUP | MODE3 */ +- 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ +- 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ +- 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ +- 0x164 0x12 /* P9_42 = GPIO0_7 = eCAP0_in_PWM0_out.gpio0[7] , OUTPUT_PULLUP | MODE2 */ +- >; +- }; +- pruicss_stepper_pins: pinmux_pruicss_stepper_pins{ +- pinctrl-single,pins = < +- 0x038 0x07 // P8_16 (3) = DIR_EXT_2 = GPIO1_14 +- 0x03C 0x07 // P8_15 (4) = DIR_EXT_1 = GPIO1_15 +- 0x028 0x07 // P8_14 (5) = DIR_Z = GPIO0_26 +- 0x02C 0x07 // P8_17 (6) = STEP_X = GPIO0_27 +- 0x034 0x07 // P8_11 (22) = step_ext_2 = GPIO1_13 +- 0x030 0x07 // P8_12 (23) = Step_y = GPIO1_12 +- 0x024 0x07 // P8_13 (24) = Step_z = GPIO0_23 +- 0x020 0x07 // P8_19 (25) = Dir_y = GPIO0_22 +- 0x07C 0x07 // P8_26 = Dir_x = GPIO1_29 +- 0x078 0x07 // P9_12 = step ext 1 = GPIO1_28 +- >; +- }; +- +- stepper_fault_pins: pinmux_stepper_fault_pins{ +- pinctrl-single,pins = < +- 0x094 0x37 // P8_8 = Fault Ext 2 = GPIO2_3 gpmc_oen_ren.gpio2[3] +- 0x09C 0x37 // P8_9 = FAYLT Y = GPIO2_5 +- 0x098 0x37 // P8_10 = FAULT X = GPIO2_4 gpmc_wen.gpio2[4] +- 0x08C 0x37 // P8_18 = Fault_ext 1 = GPIO2_1 +- 0x184 0x37 // P9_24 = Fault Z = GPIO0_15 +- >; +- }; +- +- end_stop_pins: pinmux_end_stop_pins{ +- pinctrl-single,pins = < +- 0x090 0x37 // P8_7 = End stop X1 = GPIO2_2 +- 0x070 0x37 // P9_11 = End stop Y1 = GPIO0_30 +- 0x074 0x37 // P9_13 = End stop Z1 = GPIO0_31 +- 0x158 0x37 // P9_18 = End stop Z2 = GPIO0_4 +- 0x1AC 0x37 // P9_25 = End stop Y2 = GPIO3_21 +- 0x180 0x37 // P9_26 = End stop X2 = GPIO0_14 +- >; +- }; +- dallas_w1_pins: pinmux_dallas_w1_pins { +- pinctrl-single,pins = < +- 0x150 0x37 // Dallas 1W +- >; +- }; +- }; +- }; +- +- fragment@1 { +- target = <&spi1>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; +- pinctrl-names = "default"; +- pinctrl-0 = <&bone_replicape_spi1_pins>; +- cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>; +- +- stepper_control{ +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "spidev"; +- reg = <0>; +- spi-max-frequency = <16000000>; +- spi-cpha; // Stepper control has mode 1 (CPOL = 0, CPHA = 1) +- }; +- +- stepper_current{ +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "spidev"; +- reg = <1>; +- spi-max-frequency = <16000000>; +- // Stepper current has mode 0 (CPOL = 0, CPHA = 0) +- }; +- }; +- }; +- +- fragment@2{ +- target = <&pruss>; +- __overlay__{ +- status = "okay"; +- pinctrl-names = "default"; +- pinctrl-0 = <&pruicss_stepper_pins>; +- +- stepper_x{ +- pin-names = "Replic:pru-step_x", "Replic:pru-dir_x"; +- gpios = <&gpio1 27 0 +- &gpio2 29 0>; +- }; +- stepper_y{ +- pin-names = "Replic:pru-step_y", "Replic:pru-dir_y"; +- gpios =<&gpio2 12 0 +- &gpio1 22 0>; +- }; +- stepper_z{ +- pin-names = "Replic:pru-step_z", "Replic:pru-dir_z"; +- gpios = <&gpio1 23 0 +- &gpio1 26 0>; +- }; +- stepper_ext_1{ +- pin-names = "Replic:pru-step_ext_1", "Replic:pru-dir_ext_1"; +- gpios = <&gpio2 28 0 +- &gpio2 15 0>; +- }; +- stepper_ext_2{ +- pin-names = "Replic:pru-step_ext_2", "Replic:pru-dir_ext_2"; +- gpios = <&gpio2 13 0 +- &gpio2 14 0>; +- }; +- }; +- }; +- +- fragment@3 { +- target = <&ocp>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <1>; +- +- tscadc { +- compatible = "ti,ti-tscadc"; +- reg = <0x44e0d000 0x1000>; +- +- interrupt-parent = <&intc>; +- interrupts = <16>; +- ti,hwmods = "adc_tsc"; +- status = "okay"; +- +- adc { +- ti,adc-channels = <4 5 6 7>; +- }; +- }; +- +- gpio_keys { +- compatible = "gpio-keys"; +- pinctrl-names = "default"; +- pinctrl-0 = <&end_stop_pins>; +- pinctrl-1 = <&stepper_fault_pins>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- switch_x1 { +- label = "End-stop-X1"; +- debounce_interval = <50>; +- linux,code = <1>; +- gpios = <&gpio3 2 0x5>; +- gpio-key,wakeup; +- }; +- switch_x2 { +- label = "End-stop-X2"; +- debounce_interval = <50>; +- linux,code = <2>; +- gpios = <&gpio1 14 0x5>; +- gpio-key,wakeup; +- }; +- switch_y1 { +- label = "End-stop-Y1"; +- debounce_interval = <50>; +- linux,code = <3>; +- gpios = <&gpio1 30 0x5>; +- gpio-key,wakeup; +- }; +- switch_y2 { +- label = "End-stop-Y2"; +- debounce_interval = <50>; +- linux,code = <4>; +- gpios = <&gpio4 21 0x5>; +- gpio-key,wakeup; +- }; +- switch_z1 { +- label = "End-stop-Z1"; +- debounce_interval = <50>; +- linux,code = <5>; +- gpios = <&gpio1 31 0x5>; +- gpio-key,wakeup; +- }; +- switch_z2 { +- label = "End-stop-Z2"; +- debounce_interval = <50>; +- linux,code = <6>; +- gpios = <&gpio1 4 0x5>; +- gpio-key,wakeup; +- }; +- fault_x { +- label = "Fault-X"; +- debounce_interval = <50>; +- linux,code = <7>; +- gpios = <&gpio3 4 0x5>; +- gpio-key,wakeup; +- }; +- fault_y { +- label = "Fault-Y"; +- debounce_interval = <50>; +- linux,code = <8>; +- gpios = <&gpio3 5 0x5>; +- gpio-key,wakeup; +- }; +- fault_z { +- label = "Fault-Z"; +- debounce_interval = <50>; +- linux,code = <9>; +- gpios = <&gpio1 15 0x5>; +- gpio-key,wakeup; +- }; +- fault_ext_1 { +- label = "Fault-Ext-1"; +- debounce_interval = <50>; +- linux,code = <10>; +- gpios = <&gpio3 1 0x5>; +- gpio-key,wakeup; +- }; +- fault_ext_2 { +- label = "Fault-Ext-2"; +- debounce_interval = <50>; +- linux,code = <11>; +- gpios = <&gpio3 3 0x5>; +- gpio-key,wakeup; +- }; +- }; +- onewire@0 { +- compatible = "w1-gpio"; +- pinctrl-names = "default"; +- pinctrl-0 = <&dallas_w1_pins>; +- status = "okay"; +- gpios = <&gpio1 2 0>; +- }; +- }; +- }; +-}; +-- +2.0.0.rc0 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0034-cape-add-BB-BONE-AUDI-02-00A0-from-http-elinux.org-C.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0034-cape-add-BB-BONE-AUDI-02-00A0-from-http-elinux.org-C.patch new file mode 100644 index 00000000..902cd94f --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0034-cape-add-BB-BONE-AUDI-02-00A0-from-http-elinux.org-C.patch @@ -0,0 +1,145 @@ +From 4b49f3dfabd4b766002a78a50578e6fa371f6500 Mon Sep 17 00:00:00 2001 +From: Robert Nelson +Date: Wed, 14 May 2014 08:52:25 -0500 +Subject: [PATCH 34/34] cape: add BB-BONE-AUDI-02-00A0 from: + http://elinux.org/CircuitCo:Audio_Cape_RevB + +Signed-off-by: Robert Nelson +--- + firmware/Makefile | 1 + + firmware/capes/BB-BONE-AUDI-02-00A0.dts | 111 ++++++++++++++++++++++++++++++++ + 2 files changed, 112 insertions(+) + create mode 100644 firmware/capes/BB-BONE-AUDI-02-00A0.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index 6e3f77a..d09a047 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -150,6 +150,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + cape-bone-lcd3-00A0.dtbo \ + cape-bone-lcd3-00A2.dtbo \ + BB-BONE-AUDI-01-00A0.dtbo \ ++ BB-BONE-AUDI-02-00A0.dtbo \ + BB-BONE-LCD4-01-00A0.dtbo \ + BB-BONE-LCD4-01-00A1.dtbo \ + BB-BONE-LCD7-01-00A2.dtbo \ +diff --git a/firmware/capes/BB-BONE-AUDI-02-00A0.dts b/firmware/capes/BB-BONE-AUDI-02-00A0.dts +new file mode 100644 +index 0000000..0d3b9ec +--- /dev/null ++++ b/firmware/capes/BB-BONE-AUDI-02-00A0.dts +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-AUDI-02"; ++ version = "00A0", "A0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header uses */ ++ "P9.31", /* mcasp0: mcasp0_aclkx */ ++ "P9.29", /* mcasp0: mcasp0_fsx */ ++ "P9.28", /* mcasp0: mcasp0_axr2 */ ++ "P9.25", /* mcasp0: mcasp0_ahclkx */ ++ /* the hardware ip uses */ ++ "gpio1_18", "gpio1_19", ++ "mcasp0"; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ i2c2_pins: pinmux_i2c2_pins { ++ pinctrl-single,pins = < ++ 0x150 0x72 /*spi0_scl.i2c2_sda,SLEWCTRL_SLOW | INPUT_PULLUP |MODE2*/ ++ 0x154 0x72 /*spi0_d0.i2c2_scl,SLEWCTRL_SLOW | INPUT_PULLUP | MODE2*/ ++ >; ++ }; ++ ++ bone_audio_cape_audio_pins: pinmux_bone_audio_cape_audio_pins { ++ pinctrl-single,pins = < ++ 0x1ac 0x00 /* mcasp0_ahclkx, MODE0 | INPUT */ ++ 0x19c 0x22 /* mcasp0_ahclkr, */ ++ 0x194 0x20 /* mcasp0_fsx, MODE0 | OUTPUT */ ++ 0x190 0x20 /* mcasp0_aclkr.mcasp0_aclkx, MODE0 | OUTPUT_PULLDOWN */ ++ 0x198 0x20 ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2c2>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <100000>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ ++ ++ tlv320aic3x: tlv320aic3x@18 { ++ compatible = "ti,tlv320aic3x"; ++ reg = <0x18>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&mcasp0>; ++ __overlay__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bone_audio_cape_audio_pins>; ++ ++ status = "okay"; ++ ++ op-mode = <0>; /* MCASP_IIS_MODE */ ++ tdm-slots = <2>; ++ num-serializer = <16>; ++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ ++ 2 0 1 0 ++ 0 0 0 0 ++ 0 0 0 0 ++ 0 0 0 0 ++ >; ++ tx-num-evt = <1>; ++ rx-num-evt = <1>; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ocp>; ++ __overlay__ { ++ sound { ++ compatible = "ti,da830-evm-audio"; ++ ti,model = "DA830 EVM"; ++ ti,audio-codec = <&tlv320aic3x>; ++ ti,mcasp-controller = <&mcasp0>; ++ ti,codec-clock-rate = <12000000>; ++ ti,audio-routing = ++ "Headphone Jack", "HPLOUT", ++ "Headphone Jack", "HPROUT", ++ "LINE1L", "Line In", ++ "LINE1R", "Line In"; ++ }; ++ }; ++ ++ }; ++}; +-- +2.0.0.rc0 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0035-cape-universaln-remove-P9_31.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0035-cape-universaln-remove-P9_31.patch new file mode 100644 index 00000000..295bc60b --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/capes/0035-cape-universaln-remove-P9_31.patch @@ -0,0 +1,29 @@ +From 12fb5191f9cb0ad62ccd2646e19fe694c874210f Mon Sep 17 00:00:00 2001 +From: Jason Kridner +Date: Wed, 14 May 2014 22:44:13 -0400 +Subject: [PATCH 35/35] cape-universaln: remove P9_31 + +It looks like one of the entries was missed. + +Signed-off-by: Jason Kridner +Signed-off-by: Robert Nelson +--- + firmware/capes/cape-universaln-00A0.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/firmware/capes/cape-universaln-00A0.dts b/firmware/capes/cape-universaln-00A0.dts +index a4bdbf0..2ecbd1d 100644 +--- a/firmware/capes/cape-universaln-00A0.dts ++++ b/firmware/capes/cape-universaln-00A0.dts +@@ -105,7 +105,7 @@ + /* "P9.28", Audio */ + /* "P9.29", Audio */ + "P9.30", +- "P9.31", ++/* "P9.31", Audio */ + /* "P9.32", VADC */ + /* "P9.33", AIN4 */ + /* "P9.34", AGND */ +-- +2.0.0.rc0 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0003-beaglebone-switch-uSD-to-4-bit-mode.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0003-beaglebone-switch-uSD-to-4-bit-mode.patch new file mode 100644 index 00000000..6bb1a316 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0003-beaglebone-switch-uSD-to-4-bit-mode.patch @@ -0,0 +1,25 @@ +From a4f37bbbb4155178263d47beb6322a7d1685ce43 Mon Sep 17 00:00:00 2001 +From: Koen Kooi +Date: Thu, 12 Sep 2013 09:56:37 +0200 +Subject: [PATCH 3/3] beaglebone: switch uSD to 4-bit mode + +Signed-off-by: Koen Kooi +--- + arch/arm/boot/dts/am335x-bone-common.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi +index 81d95306..89240d0 100644 +--- a/arch/arm/boot/dts/am335x-bone-common.dtsi ++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi +@@ -521,6 +521,7 @@ + &mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; ++ bus-width = <0x4>; + cd-gpios = <&gpio1 6 0>; /* gpio1 is misnamed, 0 == GPIO_ACTIVE_HIGH */ + cd-inverted; + status = "okay"; +-- +1.8.2.1 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0004-mmc-omap_hsmmc-clear-status-flags-before-starting-a-.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0004-mmc-omap_hsmmc-clear-status-flags-before-starting-a-.patch new file mode 100644 index 00000000..69a4fafd --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0004-mmc-omap_hsmmc-clear-status-flags-before-starting-a-.patch @@ -0,0 +1,47 @@ +From 38b650a239a6b47a43eaf12123d6885b0cbc596e Mon Sep 17 00:00:00 2001 +From: Francesco Lavra +Date: Sat, 29 Jun 2013 06:25:12 +0000 +Subject: [PATCH 4/4] mmc: omap_hsmmc: clear status flags before starting a new + command + +Commit 1f6b9fa40e76fffaaa0b3bd6a0bfdcf1cdc06efa consolidated writes to +the STAT register in one location, moving them from omap_hsmmc_do_irq() +to omap_hsmmc_irq(). This move has the unwanted side effect that the +controller status flags are potentially cleared after a new command has +been started as a consequence of reading the previous status flags. +This means that if the new command changes the status flags before the +IRQ routine returns, those flags may be cleared without handling the +event which asserted them, and thus missing the event. +Move the writing of the STAT register back in omap_hsmmc_do_irq(), +before handling the status flags which generated the interrupt. + +Signed-off-by: Francesco Lavra +Reviewed-and-Tested-by: Balaji T K +Signed-off-by: Chris Ball +--- + drivers/mmc/host/omap_hsmmc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index e2b97df..04daf72 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -1070,6 +1070,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) + } + } + ++ OMAP_HSMMC_WRITE(host->base, STAT, status); + if (end_cmd || ((status & CC_EN) && host->cmd)) + omap_hsmmc_cmd_done(host, host->cmd); + if ((end_trans || (status & TC_EN)) && host->mrq) +@@ -1089,7 +1090,6 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) + omap_hsmmc_do_irq(host, status); + + /* Flush posted write */ +- OMAP_HSMMC_WRITE(host->base, STAT, status); + status = OMAP_HSMMC_READ(host->base, STAT); + } + +-- +1.8.4.2 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0005-uvcvideo-Fix-data-type-for-pan-tilt-control.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0005-uvcvideo-Fix-data-type-for-pan-tilt-control.patch new file mode 100644 index 00000000..b664b689 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0005-uvcvideo-Fix-data-type-for-pan-tilt-control.patch @@ -0,0 +1,44 @@ +From 3d7e5bd097a2d61f2141afd121e4314736797b37 Mon Sep 17 00:00:00 2001 +From: Chanho Min +Date: Fri, 27 Sep 2013 01:57:40 -0300 +Subject: [PATCH 5/5] uvcvideo: Fix data type for pan/tilt control + +The pan/tilt absolute control value is signed value. If minimum value +is minus, It will be changed to plus by clamp_t() as commit 64ae9958a62. +([media] uvcvideo: Fix control value clamping for unsigned integer controls). +It leads to wrong setting of the control values. For example, +when min and max are -36000 and 36000, the setting value between of this range +is always 36000. So, its data type should be changed to signed. + +Signed-off-by: Chanho Min +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/usb/uvc/uvc_ctrl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c +index d5baab1..da3c300 100644 +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -664,7 +664,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { + .size = 32, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, +- .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, ++ .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_TILT_ABSOLUTE, +@@ -674,7 +674,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { + .size = 32, + .offset = 32, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, +- .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, ++ .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, + { + .id = V4L2_CID_PRIVACY, +-- +1.8.5.2 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0006-ti_am335x_tsc-touchscreen-jitter-fix.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0006-ti_am335x_tsc-touchscreen-jitter-fix.patch new file mode 100644 index 00000000..3be55074 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0006-ti_am335x_tsc-touchscreen-jitter-fix.patch @@ -0,0 +1,121 @@ +From bd6ee0dd6c761036f3f0e4f3a7cfeca1f5f70683 Mon Sep 17 00:00:00 2001 +From: Micka +Date: Wed, 22 Jan 2014 15:19:22 -0600 +Subject: [PATCH 6/6] ti_am335x_tsc: touchscreen jitter fix + +Signed-off-by: Micka +--- + drivers/input/touchscreen/ti_am335x_tsc.c | 46 +++++++++++++++++++------------ + 1 file changed, 28 insertions(+), 18 deletions(-) + +diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c +index 8933c91..ed83043 100644 +--- a/drivers/input/touchscreen/ti_am335x_tsc.c ++++ b/drivers/input/touchscreen/ti_am335x_tsc.c +@@ -53,6 +53,7 @@ struct titsc { + u32 config_inp[4]; + u32 bit_xp, bit_xn, bit_yp, bit_yn; + u32 inp_xp, inp_xn, inp_yp, inp_yn; ++ unsigned int prevZ; + }; + + static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) +@@ -204,11 +205,10 @@ static void titsc_read_coordinates(struct titsc *ts_dev, + u32 *x, u32 *y, u32 *z1, u32 *z2) + { + unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); +- unsigned int prev_val_x = ~0, prev_val_y = ~0; +- unsigned int prev_diff_x = ~0, prev_diff_y = ~0; +- unsigned int read, diff; ++ unsigned int read; + unsigned int i, channel; + unsigned int creads = ts_dev->coordinate_readouts; ++ unsigned int nX, nY; + + *z1 = *z2 = 0; + if (fifocount % (creads * 2 + 2)) +@@ -221,27 +221,21 @@ static void titsc_read_coordinates(struct titsc *ts_dev, + * algorithm compares the difference with that of a present value, + * if true the value is reported to the sub system. + */ ++ *x=0; ++ *y=0; ++ nX=0; ++ nY=0; + for (i = 0; i < fifocount; i++) { + read = titsc_readl(ts_dev, REG_FIFO0); + + channel = (read & 0xf0000) >> 16; + read &= 0xfff; + if (channel < creads) { +- diff = abs(read - prev_val_x); +- if (diff < prev_diff_x) { +- prev_diff_x = diff; +- *x = read; +- } +- prev_val_x = read; +- ++ (*x)+=read; ++ nX++; + } else if (channel < creads * 2) { +- diff = abs(read - prev_val_y); +- if (diff < prev_diff_y) { +- prev_diff_y = diff; +- *y = read; +- } +- prev_val_y = read; +- ++ (*y)+=read; ++ nY++; + } else if (channel < creads * 2 + 1) { + *z1 = read; + +@@ -249,6 +243,12 @@ static void titsc_read_coordinates(struct titsc *ts_dev, + *z2 = read; + } + } ++ if (nX != 0) { ++ (*x)/=nX; ++ } ++ if (nY != 0) { ++ (*y)/=nY; ++ } + } + + static irqreturn_t titsc_irq(int irq, void *dev) +@@ -258,6 +258,7 @@ static irqreturn_t titsc_irq(int irq, void *dev) + unsigned int status, irqclr = 0; + unsigned int x = 0, y = 0; + unsigned int z1, z2, z; ++ int deltaZ; + unsigned int fsm; + + status = titsc_readl(ts_dev, REG_IRQSTATUS); +@@ -288,7 +289,13 @@ static irqreturn_t titsc_irq(int irq, void *dev) + z /= z2; + z = (z + 2047) >> 12; + +- if (z <= MAX_12BIT) { ++ // calculate the deltaZ : ++ deltaZ= z - ts_dev->prevZ; ++ // save the last z calculated : ++ ts_dev->prevZ=z; ++ pr_debug("x %d y %d deltaZ %d\n", x, y, deltaZ); ++ ++ if (z <= MAX_12BIT && deltaZ>=0 && deltaZ<=10 ) { + input_report_abs(input_dev, ABS_X, x); + input_report_abs(input_dev, ABS_Y, y); + input_report_abs(input_dev, ABS_PRESSURE, z); +@@ -445,6 +452,9 @@ static int titsc_probe(struct platform_device *pdev) + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); + ++ /*init prev Z*/ ++ ts_dev->prevZ=0; ++ + /* register to the input system */ + err = input_register_device(input_dev); + if (err) +-- +1.8.5.2 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0007-omap-RS485-support-by-Michael-Musset.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0007-omap-RS485-support-by-Michael-Musset.patch new file mode 100644 index 00000000..cc014bcb --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0007-omap-RS485-support-by-Michael-Musset.patch @@ -0,0 +1,222 @@ +From 5ce42b59e6f280142a8ef7aaabe1ee525d2dff63 Mon Sep 17 00:00:00 2001 +From: Michael Musset +Date: Tue, 28 Jan 2014 10:51:50 -0600 +Subject: [PATCH 7/7] omap RS485 support by Michael Musset + +Signed-off-by: Michael Musset +--- + drivers/tty/serial/omap-serial.c | 118 ++++++++++++++++++++++++++++++++++++++- + include/uapi/linux/serial.h | 6 +- + 2 files changed, 121 insertions(+), 3 deletions(-) + +diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c +index 57d6b29..c57e5bd 100644 +--- a/drivers/tty/serial/omap-serial.c ++++ b/drivers/tty/serial/omap-serial.c +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -160,6 +161,7 @@ struct uart_omap_port { + u32 calc_latency; + struct work_struct qos_work; + struct pinctrl *pins; ++ struct serial_rs485 rs485; + }; + + #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) +@@ -268,11 +270,12 @@ static void serial_omap_enable_ms(struct uart_port *port) + pm_runtime_mark_last_busy(up->dev); + pm_runtime_put_autosuspend(up->dev); + } ++static inline void wait_for_xmitr(struct uart_omap_port *up); + + static void serial_omap_stop_tx(struct uart_port *port) + { + struct uart_omap_port *up = to_uart_omap_port(port); +- ++ int val; + pm_runtime_get_sync(up->dev); + if (up->ier & UART_IER_THRI) { + up->ier &= ~UART_IER_THRI; +@@ -283,6 +286,15 @@ static void serial_omap_stop_tx(struct uart_port *port) + + pm_runtime_mark_last_busy(up->dev); + pm_runtime_put_autosuspend(up->dev); ++ wait_for_xmitr(up); ++ if (up->rs485.flags & SER_RS485_ENABLED) { ++ if(up->rs485.delay_rts_after_send>0) { ++ udelay(up->rs485.delay_rts_after_send); ++ } ++ /* Disable RS485 TX EN */ ++ val = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; ++ gpio_set_value(up->rs485.gpio_pin, val); ++ } + } + + static void serial_omap_stop_rx(struct uart_port *port) +@@ -345,6 +357,16 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up) + static void serial_omap_start_tx(struct uart_port *port) + { + struct uart_omap_port *up = to_uart_omap_port(port); ++ int val; ++ ++ if (up->rs485.flags & SER_RS485_ENABLED) { ++ /* Enable RS485 TX EN */ ++ val = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 0 : 1; ++ gpio_set_value(up->rs485.gpio_pin, val); ++ ++ if(up->rs485.delay_rts_before_send>0) ++ udelay(up->rs485.delay_rts_before_send); ++ } + + pm_runtime_get_sync(up->dev); + serial_omap_enable_ier_thri(up); +@@ -702,6 +724,7 @@ static void serial_omap_shutdown(struct uart_port *port) + { + struct uart_omap_port *up = to_uart_omap_port(port); + unsigned long flags = 0; ++ int val; + + dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line); + +@@ -723,6 +746,12 @@ static void serial_omap_shutdown(struct uart_port *port) + serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); + serial_omap_clear_fifos(up); + ++ /* if in RS485 mode, make sure we disable the driver */ ++ if (up->rs485.flags & SER_RS485_ENABLED) { ++ val = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; ++ gpio_set_value(up->rs485.gpio_pin, val); ++ } ++ + /* + * Read data port to reset things, and then free the irq + */ +@@ -1250,6 +1279,92 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up) + + #endif + ++ ++static int ++serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) ++{ ++ int r = 0; ++ int val; ++ struct uart_omap_port *p = (struct uart_omap_port *)port; ++ ++ spin_lock(&port->lock); ++ ++ /* TODO - disable transmitter ? */ ++ ++ if (rs485conf->flags & SER_RS485_ENABLED) { ++ val = (p->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; ++ /* if using GPIO, request the resource and set it up */ ++ ++ if (rs485conf->flags & SER_RS485_USE_GPIO) { ++ /* get gpio resources if not already set */ ++ if (!(p->rs485.flags & SER_RS485_USE_GPIO) || ++ (p->rs485.gpio_pin != rs485conf->gpio_pin)) { ++ ++ r = gpio_request(rs485conf->gpio_pin, ++ "RS485 TXE"); ++ if (r) { ++ dev_warn(port->dev, ++ "Could not request GPIO %d : %d\n", ++ rs485conf->gpio_pin, r); ++ r = -EFAULT; ++ goto exit_bail; ++ } ++ ++ r = gpio_direction_output(rs485conf->gpio_pin, val); ++ if (r) { ++ dev_warn(port->dev, ++ "Could not drive GPIO %d : %d\n", ++ rs485conf->gpio_pin, r); ++ r = -EFAULT; ++ goto exit_bail; ++ } ++ ++ /* free up old pin */ ++ //TODO: What if old pin is same as current?!!?!? ++ //if (p->rs485.flags & SER_RS485_USE_GPIO) ++ //gpio_free(p->rs485.gpio_pin); ++ } ++ } else { /* RTS pin requested */ ++ dev_warn(port->dev, "Must use GPIO for RS485 Support\n"); ++ goto exit_bail; ++ } ++ } ++ p->rs485 = *rs485conf; ++ ++exit_bail: ++ spin_unlock(&port->lock); ++ return r; ++} ++ ++static int ++serial_omap_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg) ++{ ++ struct serial_rs485 rs485conf; ++ switch (cmd) { ++ case TIOCSRS485: ++ printk("rs485 v1.1\n"); ++ if (copy_from_user(&rs485conf, (struct serial_rs485 *)arg, ++ sizeof(rs485conf))) ++ return -EFAULT; ++ serial_omap_config_rs485(port, &rs485conf); ++ break; ++ ++ case TIOCGRS485: ++ printk("rs485 v1.1\n"); ++ if (copy_to_user((struct serial_rs485 *)arg, ++ &((struct uart_omap_port *)port)->rs485, ++ sizeof(rs485conf))) ++ return -EFAULT; ++ break; ++ ++ default: ++ return -ENOIOCTLCMD; ++ } ++ ++ return 0; ++} ++ ++ + static struct uart_ops serial_omap_pops = { + .tx_empty = serial_omap_tx_empty, + .set_mctrl = serial_omap_set_mctrl, +@@ -1271,6 +1386,7 @@ static struct uart_ops serial_omap_pops = { + .request_port = serial_omap_request_port, + .config_port = serial_omap_config_port, + .verify_port = serial_omap_verify_port, ++ .ioctl = serial_omap_ioctl, + #ifdef CONFIG_CONSOLE_POLL + .poll_put_char = serial_omap_poll_put_char, + .poll_get_char = serial_omap_poll_get_char, +diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h +index 5e0d0ed..9d3fcda 100644 +--- a/include/uapi/linux/serial.h ++++ b/include/uapi/linux/serial.h +@@ -116,10 +116,12 @@ struct serial_rs485 { + sending */ + #define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logical level for + RTS pin after sent*/ +-#define SER_RS485_RX_DURING_TX (1 << 4) ++ #define SER_RS485_RTS_BEFORE_SEND (1 << 3) ++ #define SER_RS485_USE_GPIO (1 << 5) + __u32 delay_rts_before_send; /* Delay before send (milliseconds) */ + __u32 delay_rts_after_send; /* Delay after send (milliseconds) */ +- __u32 padding[5]; /* Memory is cheap, new structs ++ __u32 gpio_pin; /* GPIO Pin Index */ ++ __u32 padding[4]; /* Memory is cheap, new structs + are a royal PITA .. */ + }; + +-- +1.8.5.3 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0008-deb-pkg-sync-with-v3.14.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0008-deb-pkg-sync-with-v3.14.patch new file mode 100644 index 00000000..229e99a6 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/fixes/0008-deb-pkg-sync-with-v3.14.patch @@ -0,0 +1,292 @@ +From fdc29e03daea8f2333b71b2a4d671545b78f4747 Mon Sep 17 00:00:00 2001 +From: Robert Nelson +Date: Mon, 31 Mar 2014 14:48:05 -0500 +Subject: [PATCH 8/8] deb-pkg: sync with v3.14 + +Signed-off-by: Robert Nelson +--- + scripts/package/builddeb | 182 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 129 insertions(+), 53 deletions(-) + +diff --git a/scripts/package/builddeb b/scripts/package/builddeb +index a5f197b..f46e4dd 100644 +--- a/scripts/package/builddeb ++++ b/scripts/package/builddeb +@@ -25,8 +25,44 @@ create_package() { + chown -R root:root "$pdir" + chmod -R go-w "$pdir" + ++ # Attempt to find the correct Debian architecture ++ local forcearch="" debarch="" ++ case "$UTS_MACHINE" in ++ i386|ia64|alpha) ++ debarch="$UTS_MACHINE" ;; ++ x86_64) ++ debarch=amd64 ;; ++ sparc*) ++ debarch=sparc ;; ++ s390*) ++ debarch=s390 ;; ++ ppc*) ++ debarch=powerpc ;; ++ parisc*) ++ debarch=hppa ;; ++ mips*) ++ debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo el || true) ;; ++ arm*) ++ debarch=arm$(grep -q CONFIG_AEABI=y $KCONFIG_CONFIG && echo el || true) ;; ++ *) ++ echo "" >&2 ++ echo "** ** ** WARNING ** ** **" >&2 ++ echo "" >&2 ++ echo "Your architecture doesn't have it's equivalent" >&2 ++ echo "Debian userspace architecture defined!" >&2 ++ echo "Falling back to using your current userspace instead!" >&2 ++ echo "Please add support for $UTS_MACHINE to ${0} ..." >&2 ++ echo "" >&2 ++ esac ++ if [ -n "$KBUILD_DEBARCH" ] ; then ++ debarch="$KBUILD_DEBARCH" ++ fi ++ if [ -n "$debarch" ] ; then ++ forcearch="-DArchitecture=$debarch" ++ fi ++ + # Create the package +- dpkg-gencontrol -p$pname -P"$pdir" ++ dpkg-gencontrol -isp $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir" + dpkg --build "$pdir" .. + } + +@@ -42,49 +78,35 @@ tmpdir="$objtree/debian/tmp" + fwdir="$objtree/debian/fwtmp" + kernel_headers_dir="$objtree/debian/hdrtmp" + libc_headers_dir="$objtree/debian/headertmp" ++dbg_dir="$objtree/debian/dbgtmp" + packagename=linux-image-$version +-fwpackagename=linux-firmware-image ++fwpackagename=linux-firmware-image-$version + kernel_headers_packagename=linux-headers-$version + libc_headers_packagename=linux-libc-dev +- +-# Attempt to find the correct Debian architecture +-case "$UTS_MACHINE" in +-i386|ia64|alpha) +- debarch="$UTS_MACHINE" ;; +-x86_64) +- debarch=amd64 ;; +-sparc*) +- debarch=sparc ;; +-s390*) +- debarch=s390 ;; +-ppc*) +- debarch=powerpc ;; +-parisc*) +- debarch=hppa ;; +-mips*) +- debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;; +-arm*) +- debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;; +-*) +- echo "" >&2 +- echo "** ** ** WARNING ** ** **" >&2 +- echo "" >&2 +- echo "Your architecture doesn't have it's equivalent" >&2 +- echo "Debian userspace architecture defined!" >&2 +- echo "Falling back to using your current userspace instead!" >&2 +- echo "Please add support for $UTS_MACHINE to ${0} ..." >&2 +- echo "" >&2 +-esac +-if [ -n "$KBUILD_DEBARCH" ] ; then +- debarch="$KBUILD_DEBARCH" +-fi ++dbg_packagename=$packagename-dbg + + if [ "$ARCH" = "um" ] ; then + packagename=user-mode-linux-$version + fi + ++# Not all arches have the same installed path in debian ++# XXX: have each arch Makefile export a variable of the canonical image install ++# path instead ++case $ARCH in ++um) ++ installed_image_path="usr/bin/linux-$version" ++ ;; ++parisc|mips|powerpc) ++ installed_image_path="boot/vmlinux-$version" ++ ;; ++*) ++ installed_image_path="boot/vmlinuz-$version" ++esac ++ ++BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)" ++ + # Setup the directory structure +-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" ++rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" + mkdir -m 755 -p "$tmpdir/DEBIAN" + mkdir -p "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename" + mkdir -m 755 -p "$fwdir/DEBIAN" +@@ -97,26 +119,29 @@ mkdir -p "$kernel_headers_dir/lib/modules/$version/" + if [ "$ARCH" = "um" ] ; then + mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin" + fi ++if [ -n "$BUILD_DEBUG" ] ; then ++ mkdir -p "$dbg_dir/usr/share/doc/$dbg_packagename" ++ mkdir -m 755 -p "$dbg_dir/DEBIAN" ++fi + + # Build and install the kernel + if [ "$ARCH" = "um" ] ; then + $MAKE linux + cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map" +- cp .config "$tmpdir/usr/share/doc/$packagename/config" ++ cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config" + gzip "$tmpdir/usr/share/doc/$packagename/config" +- cp $KBUILD_IMAGE "$tmpdir/usr/bin/linux-$version" + else + cp System.map "$tmpdir/boot/System.map-$version" +- cp .config "$tmpdir/boot/config-$version" +- # Not all arches include the boot path in KBUILD_IMAGE +- if [ -e $KBUILD_IMAGE ]; then +- cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version" +- else +- cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version" +- fi ++ cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version" ++fi ++# Not all arches include the boot path in KBUILD_IMAGE ++if [ -e $KBUILD_IMAGE ]; then ++ cp $KBUILD_IMAGE "$tmpdir/$installed_image_path" ++else ++ cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/$installed_image_path" + fi + +-if grep -q '^CONFIG_MODULES=y' .config ; then ++if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then + INSTALL_MOD_PATH="$tmpdir" $MAKE KBUILD_SRC= modules_install + rm -f "$tmpdir/lib/modules/$version/build" + rm -f "$tmpdir/lib/modules/$version/source" +@@ -124,6 +149,20 @@ if grep -q '^CONFIG_MODULES=y' .config ; then + mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/" + rmdir "$tmpdir/lib/modules/$version" + fi ++ if [ -n "$BUILD_DEBUG" ] ; then ++ ( ++ cd $tmpdir ++ for module in $(find lib/modules/ -name *.ko); do ++ mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module) ++ # only keep debug symbols in the debug file ++ objcopy --only-keep-debug $module $dbg_dir/usr/lib/debug/$module ++ # strip original module from debug symbols ++ objcopy --strip-debug $module ++ # then add a link to those ++ objcopy --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $module ++ done ++ ) ++ fi + fi + + if [ "$ARCH" != "um" ]; then +@@ -133,8 +172,15 @@ fi + + # Install the maintainer scripts + # Note: hook scripts under /etc/kernel are also executed by official Debian +-# kernel packages, as well as kernel packages built using make-kpkg ++# kernel packages, as well as kernel packages built using make-kpkg. ++# make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and ++# so do we; recent versions of dracut and initramfs-tools will obey this. + debhookdir=${KDEB_HOOKDIR:-/etc/kernel} ++if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then ++ want_initrd=Yes ++else ++ want_initrd=No ++fi + for script in postinst postrm preinst prerm ; do + mkdir -p "$tmpdir$debhookdir/$script.d" + cat < "$tmpdir/DEBIAN/$script" +@@ -145,7 +191,10 @@ set -e + # Pass maintainer script parameters to hook scripts + export DEB_MAINT_PARAMS="\$*" + +-test -d $debhookdir/$script.d && run-parts --arg="$version" $debhookdir/$script.d ++# Tell initramfs builder whether it's wanted ++export INITRD=$want_initrd ++ ++test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d + exit 0 + EOF + chmod 755 "$tmpdir/DEBIAN/$script" +@@ -230,8 +279,8 @@ else + Package: $packagename + Provides: linux-image, linux-image-2.6, linux-modules-$version + Suggests: $fwpackagename +-Architecture: $debarch +-Description: Linux kernel, version $version on $debarch ++Architecture: any ++Description: Linux kernel, version $version + This package contains the Linux kernel, modules and corresponding other + files, version: $version. + EOF +@@ -241,21 +290,22 @@ fi + # Build header package + (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles") + (cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles") +-(cd $objtree; find arch/$SRCARCH/include .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles") ++(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles") + destdir=$kernel_headers_dir/usr/src/linux-headers-$version + mkdir -p "$destdir" + (cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -) + (cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -) ++(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be + ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build" + rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles" + + cat <> debian/control + + Package: $kernel_headers_packagename +-Architecture: $debarch + Provides: linux-headers, linux-headers-2.6 +-Description: Linux kernel headers for $KERNELRELEASE on $debarch +- This package provides kernel header files for $KERNELRELEASE on $debarch ++Architecture: any ++Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch} ++ This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch} + . + This is useful for people who need to build external modules + EOF +@@ -294,4 +344,30 @@ fi + + create_package "$packagename" "$tmpdir" + ++if [ -n "$BUILD_DEBUG" ] ; then ++ # Build debug package ++ # Different tools want the image in different locations ++ # perf ++ mkdir -p $dbg_dir/usr/lib/debug/lib/modules/$version/ ++ cp vmlinux $dbg_dir/usr/lib/debug/lib/modules/$version/ ++ # systemtap ++ mkdir -p $dbg_dir/usr/lib/debug/boot/ ++ ln -s ../lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/boot/vmlinux-$version ++ # kdump-tools ++ ln -s lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/vmlinux-$version ++ ++ cat <> debian/control ++ ++Package: $dbg_packagename ++Section: debug ++Provides: linux-debug, linux-debug-$version ++Architecture: any ++Description: Linux kernel debugging symbols for $version ++ This package will come in handy if you need to debug the kernel. It provides ++ all the necessary debug symbols for the kernel and its modules. ++EOF ++ ++ create_package "$dbg_packagename" "$dbg_dir" ++fi ++ + exit 0 +-- +1.9.1 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/logibone/0001-Instering-Logibone-driver-into-kernel.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/logibone/0001-Instering-Logibone-driver-into-kernel.patch new file mode 100644 index 00000000..ae5efed1 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/logibone/0001-Instering-Logibone-driver-into-kernel.patch @@ -0,0 +1,920 @@ +From 96ca259a184413ae71ed89b91cdb9c8a7c9d5f2b Mon Sep 17 00:00:00 2001 +From: Jonathan Piat +Date: Mon, 28 Apr 2014 23:13:03 +0200 +Subject: [PATCH 1/3] Instering Logibone driver into kernel + +--- + drivers/misc/cape/beaglebone/Kconfig | 2 + + drivers/misc/cape/beaglebone/Makefile | 1 + + drivers/misc/cape/beaglebone/logibone/Kconfig | 6 + + drivers/misc/cape/beaglebone/logibone/Makefile | 2 + + drivers/misc/cape/beaglebone/logibone/config.c | 234 +++++++++++ + drivers/misc/cape/beaglebone/logibone/config.h | 6 + + drivers/misc/cape/beaglebone/logibone/drvr.h | 35 ++ + drivers/misc/cape/beaglebone/logibone/generic.h | 11 + + drivers/misc/cape/beaglebone/logibone/ioctl.c | 20 + + drivers/misc/cape/beaglebone/logibone/ioctl.h | 13 + + drivers/misc/cape/beaglebone/logibone/main_dma.c | 490 ++++++++++++++++++++++ + 11 files changed, 822 insertions(+) + create mode 100644 drivers/misc/cape/beaglebone/logibone/Kconfig + create mode 100644 drivers/misc/cape/beaglebone/logibone/Makefile + create mode 100644 drivers/misc/cape/beaglebone/logibone/config.c + create mode 100644 drivers/misc/cape/beaglebone/logibone/config.h + create mode 100644 drivers/misc/cape/beaglebone/logibone/drvr.h + create mode 100644 drivers/misc/cape/beaglebone/logibone/generic.h + create mode 100644 drivers/misc/cape/beaglebone/logibone/ioctl.c + create mode 100644 drivers/misc/cape/beaglebone/logibone/ioctl.h + create mode 100644 drivers/misc/cape/beaglebone/logibone/main_dma.c + +diff --git a/drivers/misc/cape/beaglebone/Kconfig b/drivers/misc/cape/beaglebone/Kconfig +index ae58216..9569924 100644 +--- a/drivers/misc/cape/beaglebone/Kconfig ++++ b/drivers/misc/cape/beaglebone/Kconfig +@@ -46,3 +46,4 @@ + help + Say Y here to include support for the Nixie Cape + ++source "drivers/misc/cape/beaglebone/logibone/Kconfig" +diff --git a/drivers/misc/cape/beaglebone/Makefile b/drivers/misc/cape/beaglebone/Makefile +index 097e25b..e8187b9 100644 +--- a/drivers/misc/cape/beaglebone/Makefile ++++ b/drivers/misc/cape/beaglebone/Makefile +@@ -9,3 +9,4 @@ obj-$(CONFIG_CAPE_BEAGLEBONE) += capemgr.o + obj-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += cape-bone-geiger.o + obj-$(CONFIG_CAPE_BEAGLEBONE_ARGUS) += cape-bone-argus.o + obj-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += cape-bone-nixie.o ++obj-y += logibone/ +diff --git a/drivers/misc/cape/beaglebone/logibone/Kconfig b/drivers/misc/cape/beaglebone/logibone/Kconfig +new file mode 100644 +index 0000000..2d2e891 +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/Kconfig +@@ -0,0 +1,6 @@ ++config CAPE_LOGIBONE_R1 ++ tristate "Beaglebone Logibone Cape" ++ depends on CAPE_BEAGLEBONE ++ default n ++ help ++ Say Y here to include support for the Nixie Cape +diff --git a/drivers/misc/cape/beaglebone/logibone/Makefile b/drivers/misc/cape/beaglebone/logibone/Makefile +new file mode 100644 +index 0000000..9a1833f +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_CAPE_LOGIBONE_R1) += logibone_r1_dma.o ++logibone_r1_dma-objs := main_dma.o config.o ioctl.o +diff --git a/drivers/misc/cape/beaglebone/logibone/config.c b/drivers/misc/cape/beaglebone/logibone/config.c +new file mode 100644 +index 0000000..8064816 +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/config.c +@@ -0,0 +1,234 @@ ++#include ++#include ++#include ++#include ++#include ++ ++ ++//SSI ++#define SSI_CLK 110 ++#define SSI_DATA 112 ++#define SSI_DONE 3 ++#define SSI_PROG 5 ++#define SSI_INIT 2 ++#define MODE0 0 ++#define MODE1 1 ++#define SSI_DELAY 1 ++ ++//GPIO ++#define GPIO3_BASE 0x481AE000 ++#define GPIO3_SETDATAOUT *(gpio_regs+1) ++#define GPIO3_CLEARDATAOUT *(gpio_regs) ++ ++//I2C ++#define I2C_IO_EXP_CONFIG_REG 0x03 ++#define I2C_IO_EXP_IN_REG 0x00 ++#define I2C_IO_EXP_OUT_REG 0x01 ++ ++ ++volatile unsigned * gpio_regs; ++ ++ ++static inline void __delay_cycles(unsigned long cycles) ++{ ++ while (cycles != 0) { ++ cycles--; ++ } ++} ++ ++static inline void ssiSetClk(void) ++{ ++ //gpio_set_value(SSI_CLK, 1); ++ GPIO3_SETDATAOUT = (1 << 14); ++} ++ ++static inline void ssiClearClk(void) ++{ ++ //gpio_set_value(SSI_CLK, 0); ++ GPIO3_CLEARDATAOUT = (1 << 14); ++} ++ ++static inline void ssiSetData(void) ++{ ++ //gpio_set_value(SSI_DATA, 1); ++ GPIO3_SETDATAOUT = (1 << 16); ++} ++ ++static inline void ssiClearData(void) ++{ ++ //gpio_set_value(SSI_DATA, 0); ++ GPIO3_CLEARDATAOUT = (1 << 16); ++} ++ ++static inline void serialConfigWriteByte(unsigned char val) ++{ ++ unsigned char bitCount = 0; ++ unsigned char valBuf = val; ++ ++ for (bitCount = 0; bitCount < 8; bitCount++) { ++ ssiClearClk(); ++ ++ if ((valBuf & 0x80) != 0) { ++ ssiSetData(); ++ } else { ++ ssiClearData(); ++ } ++ ++ //__delay_cycles(SSI_DELAY); ++ ssiSetClk(); ++ valBuf = (valBuf << 1); ++ //__delay_cycles(SSI_DELAY); ++ } ++} ++ ++static inline void i2c_set_pin(struct i2c_client * io_cli, unsigned char pin, unsigned char val) ++{ ++ unsigned char i2c_buffer[2]; ++ ++ i2c_buffer[0] = I2C_IO_EXP_OUT_REG; ++ i2c_master_send(io_cli, i2c_buffer, 1); ++ i2c_master_recv(io_cli, &i2c_buffer[1], 1); ++ ++ if (val == 1) { ++ i2c_buffer[1] |= (1 << pin); ++ } else { ++ i2c_buffer[1] &= ~(1 << pin); ++ } ++ ++ i2c_master_send(io_cli, i2c_buffer, 2); ++} ++ ++static inline unsigned char i2c_get_pin(struct i2c_client * io_cli, unsigned char pin) ++{ ++ unsigned char i2c_buffer; ++ ++ i2c_buffer = I2C_IO_EXP_IN_REG; ++ i2c_master_send(io_cli, &i2c_buffer, 1); ++ i2c_master_recv(io_cli, &i2c_buffer, 1); ++ //printk("reading value %x \n", i2c_buffer); ++ ++ return ((i2c_buffer >> pin) & 0x01); ++} ++ ++int loadBitFile(struct i2c_client * io_cli, const unsigned char * bitBuffer_user, const unsigned int length) ++{ ++ int iCfg; ++ unsigned long int i; ++ unsigned long int timer = 0; ++ unsigned char * bitBuffer; ++ unsigned char i2c_buffer[4]; ++ ++ //request_mem_region(GPIO3_BASE + 0x190, 8, gDrvrName); ++ gpio_regs = ioremap_nocache(GPIO3_BASE + 0x190, 2 * sizeof(int)); ++ ++ bitBuffer = kmalloc(length, GFP_KERNEL); ++ ++ if (bitBuffer == NULL || copy_from_user(bitBuffer, bitBuffer_user, length)) { ++ printk("Failed allocate buffer for configuration file \n"); ++ ++ return -ENOTTY; ++ } ++ ++ iCfg = gpio_request(SSI_CLK, "ssi_clk"); ++ ++ if (iCfg < 0) { ++ printk("Failed to take control over ssi_clk pin \n"); ++ ++ return -ENOTTY; ++ } ++ ++ iCfg = gpio_request(SSI_DATA, "ssi_data"); ++ ++ if (iCfg < 0) { ++ printk("Failed to take control over ssi_data pin \n"); ++ ++ return -ENOTTY; ++ } ++ ++ i2c_buffer[0] = I2C_IO_EXP_CONFIG_REG; ++ i2c_buffer[1] = 0xFF; ++ i2c_buffer[1] &= ~((1 << SSI_PROG) | (1 << MODE1) | (1 << MODE0)); ++ i2c_master_send(io_cli, i2c_buffer, 2); // set SSI_PROG, MODE0, MODE1 as output others as inputs ++ i2c_set_pin(io_cli, MODE0, 1); ++ i2c_set_pin(io_cli, MODE1, 1); ++ i2c_set_pin(io_cli, SSI_PROG, 0); ++ ++ gpio_direction_output(SSI_CLK, 0); ++ gpio_direction_output(SSI_DATA, 0); ++ ++ gpio_set_value(SSI_CLK, 0); ++ i2c_set_pin(io_cli, SSI_PROG, 1); ++ __delay_cycles(10 * SSI_DELAY); ++ i2c_set_pin(io_cli, SSI_PROG, 0); ++ __delay_cycles(5 * SSI_DELAY); ++ ++ while (i2c_get_pin(io_cli, SSI_INIT) > 0 && timer < 200) ++ timer++; // waiting for init pin to go down ++ ++ if (timer >= 200) { ++ printk("FPGA did not answer to prog request, init pin not going low \n"); ++ i2c_set_pin(io_cli, SSI_PROG, 1); ++ gpio_free(SSI_CLK); ++ gpio_free(SSI_DATA); ++ ++ return -ENOTTY; ++ } ++ ++ timer = 0; ++ __delay_cycles(5 * SSI_DELAY); ++ i2c_set_pin(io_cli, SSI_PROG, 1); ++ ++ while (i2c_get_pin(io_cli, SSI_INIT) == 0 && timer < 256) { // need to find a better way ... ++ timer++; // waiting for init pin to go up ++ } ++ ++ if (timer >= 256) { ++ printk("FPGA did not answer to prog request, init pin not going high \n"); ++ gpio_free(SSI_CLK); ++ gpio_free(SSI_DATA); ++ ++ return -ENOTTY; ++ } ++ ++ timer = 0; ++ printk("Starting configuration of %d bits \n", length * 8); ++ ++ for (i = 0; i < length; i++) { ++ serialConfigWriteByte(bitBuffer[i]); ++ schedule(); ++ } ++ ++ printk("Waiting for done pin to go high \n"); ++ ++ while (timer < 50) { ++ ssiClearClk(); ++ __delay_cycles(SSI_DELAY); ++ ssiSetClk(); ++ __delay_cycles(SSI_DELAY); ++ timer++; ++ } ++ ++ gpio_set_value(SSI_CLK, 0); ++ gpio_set_value(SSI_DATA, 1); ++ ++ if (i2c_get_pin(io_cli, SSI_DONE) == 0) { ++ printk("FPGA prog failed, done pin not going high \n"); ++ gpio_free(SSI_CLK); ++ gpio_free(SSI_DATA); ++ ++ return -ENOTTY; ++ } ++ ++ i2c_buffer[0] = I2C_IO_EXP_CONFIG_REG; ++ i2c_buffer[1] = 0xDC; ++ i2c_master_send(io_cli, i2c_buffer, 2); // set all unused config pins as input (keeping mode pins and PROG as output) ++ gpio_direction_input(SSI_CLK); ++ gpio_direction_input(SSI_DATA); ++ gpio_free(SSI_CLK); ++ gpio_free(SSI_DATA); ++ iounmap(gpio_regs); ++ //release_mem_region(GPIO3_BASE + 0x190, 8); ++ kfree(bitBuffer); ++ ++ return length; ++} +diff --git a/drivers/misc/cape/beaglebone/logibone/config.h b/drivers/misc/cape/beaglebone/logibone/config.h +new file mode 100644 +index 0000000..f2e3f66 +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/config.h +@@ -0,0 +1,6 @@ ++#ifndef __CONFIG_H__ ++#define __CONFIG_H__ ++ ++int loadBitFile(struct i2c_client * io_cli, const unsigned char * bitBuffer_user, const unsigned int length); ++ ++#endif +diff --git a/drivers/misc/cape/beaglebone/logibone/drvr.h b/drivers/misc/cape/beaglebone/logibone/drvr.h +new file mode 100644 +index 0000000..2051369 +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/drvr.h +@@ -0,0 +1,35 @@ ++#ifndef __DRVR_H__ ++#define __DRVR_H__ ++ ++#include ++ ++enum drvr_type{ ++ prog, ++ mem ++}; ++ ++struct drvr_prog{ ++ struct i2c_client * i2c_io; ++}; ++ ++ ++struct drvr_mem{ ++ unsigned short * base_addr; ++ unsigned short * virt_addr; ++ unsigned char * dma_buf; ++ int dma_chan; ++}; ++ ++union drvr_data{ ++ struct drvr_prog prog; ++ struct drvr_mem mem; ++}; ++ ++struct drvr_device{ ++ enum drvr_type type; ++ union drvr_data data; ++ struct cdev cdev; ++ unsigned char opened; ++}; ++ ++#endif +diff --git a/drivers/misc/cape/beaglebone/logibone/generic.h b/drivers/misc/cape/beaglebone/logibone/generic.h +new file mode 100644 +index 0000000..54a82a4 +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/generic.h +@@ -0,0 +1,11 @@ ++#define DEVICE_NAME "logibone" ++#define DEVICE_NAME_MEM "logibone_mem" ++ ++//I2C ++#define I2C_IO_EXP_ADDR 0x24 ++ ++//FPGA ++#define FPGA_BASE_ADDR 0x01000000 ++#define FPGA_MEM_SIZE 131072 ++ ++#define MAX_DMA_TRANSFER_IN_BYTES (32768) +diff --git a/drivers/misc/cape/beaglebone/logibone/ioctl.c b/drivers/misc/cape/beaglebone/logibone/ioctl.c +new file mode 100644 +index 0000000..84be5fd +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/ioctl.c +@@ -0,0 +1,20 @@ ++#include ++#include ++#include ++#include /* copy_to_user */ ++#include "ioctl.h" ++#include "drvr.h" ++ ++ ++long ioctl_init() { ++ return 0; ++} ++ ++void ioctl_exit() { ++} ++ ++long dm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){ ++ printk("ioctl failed \n"); ++ ++ return -ENOTTY; ++} +diff --git a/drivers/misc/cape/beaglebone/logibone/ioctl.h b/drivers/misc/cape/beaglebone/logibone/ioctl.h +new file mode 100644 +index 0000000..89e2419 +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/ioctl.h +@@ -0,0 +1,13 @@ ++#ifndef __IOCTL_H__ ++#define __IOCTL_H__ ++ ++#include ++#include ++ ++#define MAJOR_NUM 100 ++ ++long ioctl_init(void); ++void ioctl_exit(void); ++long dm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); ++ ++#endif +diff --git a/drivers/misc/cape/beaglebone/logibone/main_dma.c b/drivers/misc/cape/beaglebone/logibone/main_dma.c +new file mode 100644 +index 0000000..8228b33 +--- /dev/null ++++ b/drivers/misc/cape/beaglebone/logibone/main_dma.c +@@ -0,0 +1,490 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* copy_to_user */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++//device tree support ++#include ++#include ++#include ++#include ++#include ++#include "generic.h" ++#include "config.h" ++#include "drvr.h" ++#include "ioctl.h" ++ ++ ++//#define PROFILE //uncoment to enable code profile ++ ++static int dm_open(struct inode *inode, struct file *filp); ++static int dm_release(struct inode *inode, struct file *filp); ++static ssize_t dm_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos); ++static ssize_t dm_read(struct file *filp, char *buf, size_t count, loff_t *f_pos); ++static int edma_memtomemcpy(int count, unsigned long src_addr, unsigned long trgt_addr, int dma_ch); ++static void dma_callback(unsigned lch, u16 ch_status, void *data); ++ ++ ++static struct i2c_board_info io_exp_info= { ++ I2C_BOARD_INFO("fpga_ctrl", I2C_IO_EXP_ADDR), ++}; ++ ++static struct file_operations dm_ops = { ++ .read = dm_read, ++ .write = dm_write, ++ .compat_ioctl = dm_ioctl, ++ .unlocked_ioctl = dm_ioctl, ++ .open = dm_open, ++ .release = dm_release, ++}; ++ ++ ++static dma_addr_t dmaphysbuf = 0; ++static volatile int irqraised1 = 0; ++static unsigned char gDrvrMajor = 0; ++static struct device * prog_device; ++static struct class * drvr_class; ++static struct drvr_device * drvr_devices; ++static struct completion dma_comp; ++ ++ ++#ifdef PROFILE ++ ++static struct timespec start_ts, end_ts ; //profile timer ++ ++inline void start_profile() { ++ getnstimeofday(&start_ts); ++} ++ ++inline void stop_profile() { ++ getnstimeofday(&end_ts); ++} ++ ++inline void compute_bandwidth(const unsigned int nb_byte) { ++ struct timespec dt=timespec_sub(end_ts,start_ts); ++ long elapsed_u_time=dt.tv_sec*1000000+dt.tv_nsec/1000; ++ ++ printk("Time=%ld us\n",elapsed_u_time); ++ printk("Bandwidth=%d kBytes/s\n",1000000*(nb_byte>>10)/elapsed_u_time); ++} ++ ++#endif ++ ++ ++ssize_t writeMem(struct file *filp, const char *buf, size_t count, loff_t *f_pos) ++{ ++ unsigned short int transfer_size; ++ ssize_t transferred = 0; ++ unsigned long src_addr, trgt_addr; ++ struct drvr_mem * mem_to_write = &(((struct drvr_device *) filp->private_data)->data.mem); ++/* ++ if (count % 2 != 0) { ++ printk("%s: write: Transfer must be 16bits aligned.\n", DEVICE_NAME); ++ ++ return -1; ++ } ++*/ ++ if (count < MAX_DMA_TRANSFER_IN_BYTES) { ++ transfer_size = count; ++ } else { ++ transfer_size = MAX_DMA_TRANSFER_IN_BYTES; ++ } ++ ++ if (mem_to_write->dma_buf == NULL) { ++ printk("failed to allocate DMA buffer \n"); ++ ++ return -1; ++ } ++ ++ trgt_addr = (unsigned long) &(mem_to_write->base_addr[(*f_pos)]); ++ src_addr = (unsigned long) dmaphysbuf; ++ ++ if (copy_from_user(mem_to_write->dma_buf, buf, transfer_size)) { ++ return -1; ++ } ++ ++ while (transferred < count) { ++ ++#ifdef PROFILE ++ printk("Write \n"); ++ start_profile(); ++#endif ++ ++ if (edma_memtomemcpy(transfer_size, src_addr, trgt_addr, mem_to_write->dma_chan) < 0) { ++ printk("%s: write: Failed to trigger EDMA transfer.\n", DEVICE_NAME); ++ ++ return -1; ++ } ++ ++#ifdef PROFILE ++ stop_profile(); ++ compute_bandwidth(transfer_size); ++#endif ++ ++ trgt_addr += transfer_size; ++ transferred += transfer_size; ++ ++ if ((count - transferred) < MAX_DMA_TRANSFER_IN_BYTES) { ++ transfer_size = count - transferred; ++ } else { ++ transfer_size = MAX_DMA_TRANSFER_IN_BYTES; ++ } ++ ++ if (copy_from_user(mem_to_write->dma_buf, &buf[transferred], transfer_size)) { ++ return -1; ++ } ++ } ++ ++ return transferred; ++} ++ ++ssize_t readMem(struct file *filp, char *buf, size_t count, loff_t *f_pos) ++{ ++ unsigned short int transfer_size; ++ ssize_t transferred = 0; ++ unsigned long src_addr, trgt_addr; ++ ++ struct drvr_mem * mem_to_read = &(((struct drvr_device *) filp->private_data)->data.mem); ++/* ++ if (count % 2 != 0) { ++ printk("%s: read: Transfer must be 16bits aligned.\n", DEVICE_NAME); ++ ++ return -1; ++ } ++*/ ++ if (count < MAX_DMA_TRANSFER_IN_BYTES) { ++ transfer_size = count; ++ } else { ++ transfer_size = MAX_DMA_TRANSFER_IN_BYTES; ++ } ++ ++ if (mem_to_read->dma_buf == NULL) { ++ printk("failed to allocate DMA buffer \n"); ++ ++ return -1; ++ } ++ ++ src_addr = (unsigned long) &(mem_to_read->base_addr[(*f_pos)]); ++ trgt_addr = (unsigned long) dmaphysbuf; ++ ++ while (transferred < count) { ++ ++#ifdef PROFILE ++ printk("Read \n"); ++ start_profile(); ++#endif ++ ++ if (edma_memtomemcpy(transfer_size, src_addr, trgt_addr, mem_to_read->dma_chan) < 0) { ++ ++ printk("%s: read: Failed to trigger EDMA transfer.\n", DEVICE_NAME); ++ ++ return -1; ++ } ++ ++ if (copy_to_user(&buf[transferred], mem_to_read->dma_buf, transfer_size)) { ++ return -1; ++ } ++ ++#ifdef PROFILE ++ stop_profile(); ++ compute_bandwidth(transfer_size); ++#endif ++ ++ src_addr += transfer_size; ++ transferred += transfer_size; ++ ++ if ((count - transferred) < MAX_DMA_TRANSFER_IN_BYTES) { ++ transfer_size = (count - transferred); ++ } else { ++ transfer_size = MAX_DMA_TRANSFER_IN_BYTES; ++ } ++ } ++ ++ return transferred; ++} ++ ++static int dm_open(struct inode *inode, struct file *filp) ++{ ++ struct drvr_device ++ * dev = container_of(inode->i_cdev, struct drvr_device, cdev); ++ ++ filp->private_data = dev; /* for other methods */ ++ ++ if (dev == NULL) { ++ printk("%s: Failed to retrieve driver structure !\n", DEVICE_NAME); ++ ++ return -1; ++ } ++ ++ if (dev->opened == 1) { ++ printk("%s: module already opened\n", DEVICE_NAME); ++ ++ return 0; ++ } ++ ++ if (dev->type != prog) { ++ struct drvr_mem* mem_dev = &((dev->data).mem); ++ ++ request_mem_region((unsigned long) mem_dev->base_addr, FPGA_MEM_SIZE, DEVICE_NAME); ++ mem_dev->virt_addr = ioremap_nocache(((unsigned long) mem_dev->base_addr), FPGA_MEM_SIZE); ++ mem_dev->dma_chan = edma_alloc_channel(EDMA_CHANNEL_ANY, dma_callback, NULL, EVENTQ_0); ++ mem_dev->dma_buf = (unsigned char *) dma_alloc_coherent(NULL, MAX_DMA_TRANSFER_IN_BYTES, &dmaphysbuf, 0); ++ printk("EDMA channel %d reserved \n", mem_dev->dma_chan); ++ ++ if (mem_dev->dma_chan < 0) { ++ printk("edma_alloc_channel failed for dma_ch, error: %d\n", mem_dev->dma_chan); ++ ++ return -1; ++ } ++ ++ printk("mem interface opened \n"); ++ } ++ ++ dev->opened = 1; ++ ++ return 0; ++} ++ ++static int dm_release(struct inode *inode, struct file *filp) ++{ ++ struct drvr_device ++ * dev = container_of(inode->i_cdev, struct drvr_device, cdev); ++ ++ if (dev->opened == 0) { ++ printk("%s: module already released\n", DEVICE_NAME); ++ ++ return 0; ++ } ++ ++ if (dev->type == mem) { ++ iounmap((dev->data.mem).virt_addr); ++ release_mem_region(((unsigned long) (dev->data.mem).base_addr), FPGA_MEM_SIZE); ++ printk("%s: Release: module released\n", DEVICE_NAME); ++ dma_free_coherent(NULL, MAX_DMA_TRANSFER_IN_BYTES, (dev->data.mem).dma_buf, dmaphysbuf); ++ edma_free_channel((dev->data.mem).dma_chan); ++ } ++ ++ dev->opened = 0; ++ ++ return 0; ++} ++ ++static ssize_t dm_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) ++{ ++ struct drvr_device * dev = filp->private_data; /* for other methods */ ++ ++ switch (dev->type) { ++ case prog: ++ return loadBitFile((dev->data.prog.i2c_io), buf, count); ++ ++ case mem: ++ return writeMem(filp, buf, count, f_pos); ++ ++ default: ++ return loadBitFile((dev->data.prog.i2c_io), buf, count); ++ }; ++} ++ ++static ssize_t dm_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) ++{ ++ struct drvr_device * dev = filp->private_data; /* for other methods */ ++ ++ switch (dev->type) { ++ case prog: ++ return -1; ++ ++ case mem: ++ return readMem(filp, buf, count, f_pos); ++ ++ default: ++ return -1; ++ }; ++} ++ ++static void dm_exit(void) ++{ ++ dev_t devno = MKDEV(gDrvrMajor, 0); ++ ++ /* Get rid of our char dev entries */ ++ if (drvr_devices) { ++ int i; ++ ++ for (i = 0; i < 2; i++) { ++ if (i == 0) { ++ i2c_unregister_device(drvr_devices[i].data.prog.i2c_io); ++ } ++ ++ device_destroy(drvr_class, MKDEV(gDrvrMajor, i)); ++ cdev_del(&drvr_devices[i].cdev); ++ } ++ ++ kfree(drvr_devices); ++ } ++ ++ class_destroy(drvr_class); ++ /* cleanup_module is never called if registering failed */ ++ unregister_chrdev_region(devno, 2); ++ ++ ioctl_exit(); ++} ++ ++static int dm_init(void) ++{ ++ int result; ++ int devno; ++ struct drvr_mem * memDev; ++ struct drvr_prog * progDev; ++ struct i2c_adapter *i2c_adap; ++ ++ dev_t dev = 0; ++ result = alloc_chrdev_region(&dev, 0, 2, DEVICE_NAME); ++ gDrvrMajor = MAJOR(dev); ++ ++ if (result < 0) { ++ printk(KERN_ALERT "Registering char device failed with %d\n", gDrvrMajor); ++ ++ return result; ++ } ++ ++ drvr_devices = kmalloc(2 * sizeof(struct drvr_device), GFP_KERNEL); ++ ++ if (!drvr_devices) { ++ dm_exit(); ++ ++ return -ENOMEM; ++ } ++ ++ drvr_class = class_create(THIS_MODULE, DEVICE_NAME); ++ memset(drvr_devices, 0, 2 * sizeof(struct drvr_device)); ++ ++ /*Initializing main mdevice for prog*/ ++ devno = MKDEV(gDrvrMajor, 0); ++ drvr_devices[0].type = prog; ++ progDev = &(drvr_devices[0].data.prog); ++ prog_device = device_create(drvr_class, NULL, devno, NULL, DEVICE_NAME); // should create /dev entry for main node ++ drvr_devices[0].opened = 0; ++ ++ /*Do the i2c stuff*/ ++ i2c_adap = i2c_get_adapter(1); // todo need to check i2c adapter id ++ ++ if (i2c_adap == NULL) { ++ printk("Cannot get adapter 1 \n"); ++ dm_exit(); ++ ++ return -1; ++ } ++ ++ progDev->i2c_io = i2c_new_device(i2c_adap, &io_exp_info); ++ i2c_put_adapter(i2c_adap); //don't know what it does, seems to release the adapter ... ++ ++ if (prog_device == NULL) { ++ class_destroy(drvr_class); ++ drvr_devices[0].opened = 0; ++ dm_exit(); ++ ++ return -ENOMEM;; ++ } ++ ++ cdev_init(&(drvr_devices[0].cdev), &dm_ops); ++ drvr_devices[0].cdev.owner = THIS_MODULE; ++ drvr_devices[0].cdev.ops = &dm_ops; ++ cdev_add(&(drvr_devices[0].cdev), devno, 1); ++ //printk(KERN_INFO "'mknod /dev/%s c %d %d'.\n", DEVICE_NAME, gDrvrMajor, 0); ++ /* Initialize each device. */ ++ devno = MKDEV(gDrvrMajor, 1); ++ drvr_devices[1].type = mem; ++ memDev = &(drvr_devices[1].data.mem); ++ memDev->base_addr = (unsigned short *) (FPGA_BASE_ADDR); ++ device_create(drvr_class, prog_device, devno, NULL, DEVICE_NAME_MEM); ++ cdev_init(&(drvr_devices[1].cdev), &dm_ops); ++ (drvr_devices[1].cdev).owner = THIS_MODULE; ++ (drvr_devices[1].cdev).ops = &dm_ops; ++ cdev_add(&(drvr_devices[1].cdev), devno, 1); ++ drvr_devices[1].opened = 0; ++ init_completion(&dma_comp); ++ ++ return ioctl_init(); ++} ++ ++static int edma_memtomemcpy(int count, unsigned long src_addr, unsigned long trgt_addr, int dma_ch) ++{ ++ int result = 0; ++ struct edmacc_param param_set; ++ ++ edma_set_src(dma_ch, src_addr, INCR, W256BIT); ++ edma_set_dest(dma_ch, trgt_addr, INCR, W256BIT); ++ edma_set_src_index(dma_ch, 1, 1); ++ edma_set_dest_index(dma_ch, 1, 1); ++ /* A Sync Transfer Mode */ ++ edma_set_transfer_params(dma_ch, count, 1, 1, 1, ASYNC); //one block of one frame of one array of count bytes ++ ++ /* Enable the Interrupts on Channel 1 */ ++ edma_read_slot(dma_ch, ¶m_set); ++ param_set.opt |= ITCINTEN; ++ param_set.opt |= TCINTEN; ++ param_set.opt |= EDMA_TCC(EDMA_CHAN_SLOT(dma_ch)); ++ edma_write_slot(dma_ch, ¶m_set); ++ irqraised1 = 0u; ++ dma_comp.done = 0; ++ result = edma_start(dma_ch); ++ ++ if (result != 0) { ++ printk("%s: edma copy failed \n", DEVICE_NAME); ++ } ++ ++ wait_for_completion(&dma_comp); ++ ++ /* Check the status of the completed transfer */ ++ if (irqraised1 < 0) { ++ printk("%s: edma copy: Event Miss Occured!!!\n", DEVICE_NAME); ++ edma_stop(dma_ch); ++ result = -EAGAIN; ++ } ++ ++ return result; ++} ++ ++static void dma_callback(unsigned lch, u16 ch_status, void *data) ++{ ++ switch (ch_status) { ++ case DMA_COMPLETE: ++ irqraised1 = 1; ++ break; ++ ++ case DMA_CC_ERROR: ++ irqraised1 = -1; ++ break; ++ ++ default: ++ irqraised1 = -1; ++ break; ++ } ++ ++ complete(&dma_comp); ++} ++ ++static const struct of_device_id drvr_of_match[] = { ++ { .compatible = DEVICE_NAME, }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, drvr_of_match); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Jonathan Piat "); ++MODULE_AUTHOR("Martin Schmitt "); ++ ++module_init(dm_init); ++module_exit(dm_exit); +-- +1.7.9.5 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/logibone/0002-Adding-DTS-support-for-Logibone.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/logibone/0002-Adding-DTS-support-for-Logibone.patch new file mode 100644 index 00000000..33051627 --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/logibone/0002-Adding-DTS-support-for-Logibone.patch @@ -0,0 +1,255 @@ +From 5e143d4edab52efc968afd1a7a910aa342450975 Mon Sep 17 00:00:00 2001 +From: Jonathan Piat +Date: Mon, 28 Apr 2014 23:13:49 +0200 +Subject: [PATCH 2/3] Adding DTS support for Logibone + +--- + firmware/Makefile | 3 +- + firmware/capes/BB-BONE-LOGIBONE-00R1.dts | 221 ++++++++++++++++++++++++++++++ + 2 files changed, 224 insertions(+), 1 deletion(-) + create mode 100644 firmware/capes/BB-BONE-LOGIBONE-00R1.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index 1a74a6d..5b49b5f 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -206,7 +206,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + BB-BONE-CRYPTO-00A0.dtbo \ + bone_eqep0-00A0.dtbo \ + bone_eqep1-00A0.dtbo \ +- bone_eqep2-00A0.dtbo ++ bone_eqep2-00A0.dtbo \ ++ BB-BONE-LOGIBONE-00R1.dtbo + + # the geiger cape + fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \ +diff --git a/firmware/capes/BB-BONE-LOGIBONE-00R1.dts b/firmware/capes/BB-BONE-LOGIBONE-00R1.dts +new file mode 100644 +index 0000000..87f5e6c +--- /dev/null ++++ b/firmware/capes/BB-BONE-LOGIBONE-00R1.dts +@@ -0,0 +1,221 @@ ++/* ++ * optargs=capemgr.disable_partno=BB-BONE-EMMC-2G ++ * "arch/arm/boot/dts/am335x-boneblack.dts", find the section starting ++ * with "&mmc2 {" and in section change status = "okay" into "disabled". ++ * do once : mmc dev 1 ++ * mmc rstn 1 ++ * in uBoot or in uEnv and then delete ++ */ ++ ++ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "BB-BONE-LOGIBONE"; ++ version = "00R1"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header uses */ ++ "P8.25", /* gpmc: gpmc_ad0 */ ++ "P8.24", /* gpmc: gpmc_ad1 */ ++ "P8.5", /* gpmc: gpmc_ad2 */ ++ "P8.6", /* gpmc: gpmc_ad3 */ ++ "P8.23", /* gpmc: gpmc_ad4 */ ++ "P8.22", /* gpmc: gpmc_ad5 */ ++ "P8.3", /* gpmc: gpmc_ad6 */ ++ "P8.4", /* gpmc: gpmc_ad7 */ ++ "P8.19", /* gpmc: gpmc_ad8 */ ++ "P8.13", /* gpmc: gpmc_ad9 */ ++ "P8.14", /* gpmc: gpmc_ad10 */ ++ "P8.17", /* gpmc: gpmc_ad11 */ ++ "P8.12", /* gpmc: gpmc_ad12 */ ++ "P8.11", /* gpmc: gpmc_ad13 */ ++ "P8.16", /* gpmc: gpmc_ad14 */ ++ "P8.15", /* gpmc: gpmc_ad15 */ ++ "P9.12", /* gpmc: gpmc_ben1 */ ++ "P8.21", /* gpmc: gpmc_csn1 */ ++ "P8.18", /* gpmc: gpmc_clk */ ++ "P8.7", /* gpmc: gpmc_advn_ale */ ++ "P8.8", /* gpmc: gpmc_oen_ren */ ++ "P8.10", /* gpmc: gpmc_wen */ ++ "P8.9", /* gpmc: gpmc_ben0_cle */ ++ ++ "gpmc", ++ /* the reset pin */ ++ "eMMC_RSTn"; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ fragment@0 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ gpmc_pins: pinmux_gpmc_pins { ++ pinctrl-single,pins = < ++ 0x000 0x30 /* gpmc_ad0.gpmc_ad0 MODE0 | INPUT | PULLUP */ ++ 0x004 0x30 /* gpmc_ad1.gpmc_ad1 MODE0 | INPUT | PULLUP */ ++ 0x008 0x30 /* gpmc_ad2.gpmc_ad2 MODE0 | INPUT | PULLUP */ ++ 0x00C 0x30 /* gpmc_ad3.gpmc_ad3 MODE0 | INPUT | PULLUP */ ++ 0x010 0x30 /* gpmc_ad4.gpmc_ad4 MODE0 | INPUT | PULLUP */ ++ 0x014 0x30 /* gpmc_ad5.gpmc_ad5 MODE0 | INPUT | PULLUP */ ++ 0x018 0x30 /* gpmc_ad6.gpmc_ad6 MODE0 | INPUT | PULLUP */ ++ 0x01C 0x30 /* gpmc_ad7.gpmc_ad7 MODE0 | INPUT | PULLUP */ ++ 0x020 0x30 /* gpmc_ad8.gpmc_ad8 MODE0 | INPUT | PULLUP */ ++ 0x024 0x30 /* gpmc_ad9.gpmc_ad9 MODE0 | INPUT | PULLUP */ ++ 0x028 0x30 /* gpmc_ad10.gpmc_ad10 MODE0 | INPUT | PULLUP */ ++ 0x02C 0x30 /* gpmc_ad11.gpmc_ad11 MODE0 | INPUT | PULLUP */ ++ 0x030 0x30 /* gpmc_ad12.gpmc_ad12 MODE0 | INPUT | PULLUP */ ++ 0x034 0x30 /* gpmc_ad13.gpmc_ad13 MODE0 | INPUT | PULLUP */ ++ 0x038 0x30 /* gpmc_ad14.gpmc_ad14 MODE0 | INPUT | PULLUP */ ++ 0x03C 0x30 /* gpmc_ad15.gpmc_ad15 MODE0 | INPUT | PULLUP */ ++ 0x080 0x08 /* gpmc_cscn1.gpmc_cscn1 MODE0 | OUTPUT */ ++ 0x08C 0x28 /* gpmc_clk.gpmc_clk MODE0 | INPUT */ ++ 0x090 0x08 /* gpmc_advn_ale.gpmc_advn_ale MODE0 | OUTPUT */ ++ 0x094 0x08 /* gpmc_oen_ren.gpmc_oen_ren MODE0 | OUTPUT */ ++ 0x098 0x08 /* gpmc_wen.gpmc_wen MODE0 | OUTPUT */ ++ 0x09C 0x08 /* gpmc_ben0_cle.gpmc_ben0_cle MODE0 | OUTPUT */ ++ 0x078 0x08 /* gpmc_ben1_cle.gpmc_ben1_cle MODE0 | OUTPUT */ ++ >; ++ }; ++ ++ fpga_config_pins: pinmux_fpga_config_pins { ++ pinctrl-single,pins = < ++ /* config clk and data */ ++ 0x198 0x37 /* spi1_d1 MODE3 | INPUT | PULLUP , serial data config */ ++ 0x190 0x37 /* spi1_sclk MODE3 | INPUT | PULLUP, serial clock config */ ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpmc>; ++ depth = <1>; /* only create devices on depth 1 */ ++ ++ /* stupid warnings */ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ __overlay__ { ++ ++ status = "okay"; ++ ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gpmc_pins>; ++ ++ ++ ++ ++ /* chip select ranges */ ++ ranges = <1 0 0x01000000 0x1000000>; ++ ++ camera{ ++ compatible = "logibone_ra1"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fpga_config_pins>; ++ ++ reset = <&rstctl 0 0>; ++ reset-names = "eMMC_RSTn-LOGIBONE"; ++ ++ reg = <1 0 0x01000000>; /*CSn1*/ ++ ++ bank-width = <2>; /* GPMC_CONFIG1_DEVICESIZE(1) */ ++ ++ /*gpmc,burst-write;*/ ++ /*gpmc,burst-read;*/ ++ /*gpmc,burst-wrap;*/ ++ gpmc,sync-read; /* GPMC_CONFIG1_READTYPE_ASYNC */ ++ gpmc,sync-write; /* GPMC_CONFIG1_WRITETYPE_ASYNC */ ++ gpmc,clk-activation-ns = <0>; /* GPMC_CONFIG1_CLKACTIVATIONTIME(2) */ ++ gpmc,burst-length = <16>; /* GPMC_CONFIG1_PAGE_LEN(2) */ ++ gpmc,mux-add-data = <2>; /* GPMC_CONFIG1_MUXTYPE(2) */ ++ ++ gpmc,sync-clk-ps = <20000>; /* CONFIG2 */ ++ ++ gpmc,cs-on-ns = <0>; ++ gpmc,cs-rd-off-ns = <100>; ++ gpmc,cs-wr-off-ns = <40>; ++ ++ gpmc,adv-on-ns = <0>; /* CONFIG3 */ ++ gpmc,adv-rd-off-ns = <20>; ++ gpmc,adv-wr-off-ns = <20>; ++ ++ gpmc,we-on-ns = <20>; /* CONFIG4 */ ++ gpmc,we-off-ns = <40>; ++ gpmc,oe-on-ns = <20>; ++ gpmc,oe-off-ns = <100>; ++ ++ gpmc,page-burst-access-ns = <20>; /* CONFIG 5 */ ++ gpmc,access-ns = <80>; ++ gpmc,rd-cycle-ns = <120>; ++ gpmc,wr-cycle-ns = <60>; ++ gpmc,wr-access-ns = <40>; /* CONFIG 6 */ ++ gpmc,wr-data-mux-bus-ns = <20>; ++ ++ /*gpmc,bus-turnaround-ns = <40>;*/ /* CONFIG6:3:0 = 4 */ ++ /*gpmc,cycle2cycle-samecsen;*/ /* CONFIG6:7 = 1 */ ++ /*gpmc,cycle2cycle-delay-ns = <40>;*/ /* CONFIG6:11:8 = 4 */ ++ ++ /* not using dma engine yet, but we can get the channel number here */ ++ dmas = <&edma 20>; ++ dma-names = "logibone"; ++ ++ fpga,config { ++ i2c-adapter = <&i2c2>; ++ ++ /* need it to stop the whinning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* fake i2c device node */ ++ pca9534 { ++ compatible = "logibone"; ++ reg = <0x24>; ++ }; ++ }; ++ ++ }; ++ ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spi0>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fpga_config_pins>; ++ ++ spi0_0{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ spi0_1{ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "spidev"; ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ // Mode 0 (CPOL = 0, CPHA = 0) ++ }; ++ }; ++ }; ++ ++ }; +-- +1.7.9.5 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/machinekit/0001-Add-dir-changeable-property-to-gpio-of-helper.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/machinekit/0001-Add-dir-changeable-property-to-gpio-of-helper.patch new file mode 100644 index 00000000..84150b0e --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/machinekit/0001-Add-dir-changeable-property-to-gpio-of-helper.patch @@ -0,0 +1,26 @@ +From 638389b32b46e5da3f1788c6d1b2ea27dc4ab481 Mon Sep 17 00:00:00 2001 +From: Charles Steinkuehler +Date: Sun, 26 Jan 2014 16:17:09 +0100 +Subject: [PATCH] Add dir-changeable property to gpio-of-helper + +Signed-off-by: Charles Steinkuehler +--- + drivers/gpio/gpio-of-helper.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpio/gpio-of-helper.c b/drivers/gpio/gpio-of-helper.c +index 16a607f..1c289b2 100644 +--- a/drivers/gpio/gpio-of-helper.c ++++ b/drivers/gpio/gpio-of-helper.c +@@ -181,6 +181,8 @@ gpio_of_entry_create(struct gpio_of_helper_info *info, + req_flags |= GPIOF_OUT_INIT_LOW; + break; + } ++ if (of_property_read_bool(node, "dir-changeable")) ++ req_flags |= GPIOF_EXPORT_CHANGEABLE; + + /* request the gpio */ + err = devm_gpio_request_one(dev, gpio, req_flags, name); +-- +1.8.5.3 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/net/0007-net-cpsw-fix-irq_disable-with-threaded-interrupts.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/net/0007-net-cpsw-fix-irq_disable-with-threaded-interrupts.patch new file mode 100644 index 00000000..58dc84ba --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/net/0007-net-cpsw-fix-irq_disable-with-threaded-interrupts.patch @@ -0,0 +1,72 @@ +From f7351e25e37cdd7fab871af5f66dbebe36a3d658 Mon Sep 17 00:00:00 2001 +From: Robert Nelson +Date: Fri, 3 Jan 2014 10:39:30 -0600 +Subject: [PATCH 7/7] net/cpsw: fix irq_disable() with threaded interrupts + +https://groups.google.com/d/msg/beagleboard/mfQwHdfHyoo/SA9EnjpXoAsJ + +Signed-off-by: Eugene +Signed-off-by: Robert Nelson +--- + drivers/net/ethernet/ti/cpsw.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index 21ba53e..9c72a69 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -342,6 +342,7 @@ struct cpsw_priv { + /* snapshot of IRQ numbers */ + u32 irqs_table[4]; + u32 num_irqs; ++ bool irq_enabled; + struct cpts cpts; + }; + +@@ -458,7 +459,10 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id) + + if (likely(netif_running(priv->ndev))) { + cpsw_intr_disable(priv); +- cpsw_disable_irq(priv); ++ if (priv->irq_enabled == true) { ++ cpsw_disable_irq(priv); ++ priv->irq_enabled = false; ++ } + napi_schedule(&priv->napi); + } + +@@ -512,7 +516,10 @@ static int cpsw_poll(struct napi_struct *napi, int budget) + if ((num_total_rx + num_total_tx) < budget) { + napi_complete(napi); + cpsw_intr_enable(priv); +- cpsw_enable_irq(priv); ++ if (priv->irq_enabled == false) { ++ cpsw_enable_irq(priv); ++ priv->irq_enabled = true; ++ } + } + + return num_total_rx + num_total_rx; +@@ -812,7 +819,10 @@ static int cpsw_ndo_stop(struct net_device *ndev) + struct cpsw_priv *priv = netdev_priv(ndev); + + cpsw_info(priv, ifdown, "shutting down cpsw device\n"); +- cpsw_disable_irq(priv); ++ if (priv->irq_enabled == true) { ++ cpsw_disable_irq(priv); ++ priv->irq_enabled = false; ++ } + netif_stop_queue(priv->ndev); + if (!priv->data.disable_napi) + napi_disable(&priv->napi); +@@ -1306,6 +1316,7 @@ static int cpsw_probe(struct platform_device *pdev) + priv->dev = &ndev->dev; + priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); + priv->rx_packet_max = max(rx_packet_max, 128); ++ priv->irq_enabled = false; + + /* + * This may be required here for child devices. +-- +1.8.5.2 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline-3.8/proto/0001-add-new-default-pinmux-based-on-Proto-Cape.patch b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/proto/0001-add-new-default-pinmux-based-on-Proto-Cape.patch new file mode 100644 index 00000000..f373d24d --- /dev/null +++ b/common-bsp/recipes-kernel/linux/linux-mainline-3.8/proto/0001-add-new-default-pinmux-based-on-Proto-Cape.patch @@ -0,0 +1,347 @@ +From 361f02e8b9a87a5a5d10fc359239e4108e20fc4b Mon Sep 17 00:00:00 2001 +From: Robert Nelson +Date: Tue, 28 Jan 2014 10:06:53 -0600 +Subject: [PATCH] add new default pinmux based on Proto Cape + +http://elinux.org/CircuitCo:Basic_Proto_Cape + +load: echo "cape-bone-proto" > /sys/devices/bone_capemgr.*/slots + +Signed-off-by: Robert Nelson +--- + firmware/Makefile | 1 + + firmware/capes/cape-bone-proto-00A0.dts | 310 ++++++++++++++++++++++++++++++++ + 2 files changed, 311 insertions(+) + create mode 100644 firmware/capes/cape-bone-proto-00A0.dts + +diff --git a/firmware/Makefile b/firmware/Makefile +index e45d10b..ecc54d9 100644 +--- a/firmware/Makefile ++++ b/firmware/Makefile +@@ -191,6 +191,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \ + BB-BONE-CAM3-01-00A2.dtbo \ + BB-BONE-CAM-VVDN-00A0.dtbo \ + TT3201-001-01.dtbo \ ++ cape-bone-proto-00A0.dtbo \ + BB-BONE-SERL-03-00A1.dtbo \ + BB-BONE-BACON-00A0.dtbo \ + BB-BONE-BACONE-00A0.dtbo \ +diff --git a/firmware/capes/cape-bone-proto-00A0.dts b/firmware/capes/cape-bone-proto-00A0.dts +new file mode 100644 +index 0000000..5416d4b +--- /dev/null ++++ b/firmware/capes/cape-bone-proto-00A0.dts +@@ -0,0 +1,310 @@ ++/* ++ * Copyright (C) 2014 Robert Nelson ++ * ++ * Virtual cape http://elinux.org/CircuitCo:Basic_Proto_Cape ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "ti,beaglebone", "ti,beaglebone-black"; ++ ++ /* identification */ ++ part-number = "basic-proto"; ++ version = "00A0"; ++ ++ /* state the resources this cape uses */ ++ exclusive-use = ++ /* the pin header uses */ ++ /* gpio */ ++ "P8.7", ++ "P8.8", ++ "P8.9", ++ "P8.10", ++ "P8.19", ++ "P9.15", ++ ++ "P9.14", /* pwm: ehrpwm1A */ ++ "P9.16", /* pwm: ehrpwm1B */ ++ ++ /* spi0 */ ++ "P9.17", /* spi0_cs0 */ ++ "P9.18", /* spi0_d1 */ ++ "P9.21", /* spi0_d0 */ ++ "P9.22", /* spi0_sclk */ ++ ++ /* uart 1 */ ++ "P9.24", /* uart1_txd */ ++ "P9.26", /* uart1_rxd */ ++ ++ /* adc */ ++ "P9.33", /* AIN4 */ ++ "P9.36", /* AIN5 */ ++ "P9.35", /* AIN6 */ ++ ++ "P9.42", /* pwm: eCAP0_in_PWM0_out */ ++ ++ /* the hardware ip uses */ ++ "ehrpwm1A", ++ "ehrpwm1B", ++ "eCAP0_in_PWM0_out", ++ "spi0", ++ "tscadc", ++ "uart1"; ++ ++ fragment@0 { ++ target = <&epwmss0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&ehrpwm0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&ecap0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&epwmss1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&ehrpwm1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&epwmss2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&ehrpwm2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&ecap2>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&am33xx_pinmux>; ++ __overlay__ { ++ ++ gpio_helper_pins: pinmux_gpio_helper_pins { ++ pinctrl-single,pins = < ++ 0x020 0x47 /* P8 19 GPIO0_22: */ ++ 0x040 0x47 /* P9 15 GPIO1_16: */ ++ 0x090 0x67 /* P8 07 GPIO2_2: */ ++ 0x094 0x67 /* P8 08 GPIO2_3: */ ++ 0x098 0x67 /* P8 10 GPIO2_4: */ ++ 0x09c 0x67 /* P8 09 GPIO2_5: */ ++ >; ++ }; ++ ++ bb_spi0_pins: pinmux_bb_spi0_pins { ++ pinctrl-single,pins = < ++ 0x150 0x30 /* spi0_sclk.spi0_sclk, INPUT_PULLUP | MODE0 */ ++ 0x154 0x30 /* spi0_d0.spi0_d0, INPUT_PULLUP | MODE0 */ ++ 0x158 0x10 /* spi0_d1.spi0_d1, OUTPUT_PULLUP | MODE0 */ ++ 0x15c 0x10 /* spi0_cs0.spi0_cs0, OUTPUT_PULLUP | MODE0 */ ++ >; ++ }; ++ ++ bb_uart1_pins: pinmux_bb_uart1_pins { ++ pinctrl-single,pins = < ++ 0x184 0x20 /* P9.24 uart1_txd.uart1_txd OUTPUT */ ++ 0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd INPUT */ ++ >; ++ }; ++ ++ pwm_P9_14: pinmux_pwm_P9_14_pins { ++ pinctrl-single,pins = <0x048 0x6>; /* P9_14 (ZCZ ball U14) | MODE 6 */ ++ }; ++ ++ pwm_P9_16: pinmux_pwm_P9_16_pins { ++ pinctrl-single,pins = <0x04c 0x6>; /* P9_16 (ZCZ ball T14) | MODE 6 */ ++ }; ++ ++ pwm_P9_42: pinmux_pwm_P9_42_pins { ++ pinctrl-single,pins = <0x164 0x0>; /* P9_42 (ZCZ ball C18) | MODE 0 */ ++ }; ++ }; ++ }; ++ ++ fragment@11 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ // !!!WARNING!!! ++ // gpio-of-helper &gpio pointers are off-by-one vs. the hardware: ++ // hardware GPIO bank 0 = &gpio1 ++ gpio_export { ++ compatible = "gpio-of-helper"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gpio_helper_pins>; ++ ++ P8_07 { ++ gpio-name = "P8_07"; ++ gpio = <&gpio3 2 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_08 { ++ gpio-name = "P8_08"; ++ gpio = <&gpio3 3 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_09 { ++ gpio-name = "P8_09"; ++ gpio = <&gpio3 5 0>; ++ input; ++ dir-changeable; ++ }; ++ P8_10 { ++ gpio-name = "P8_10"; ++ gpio = <&gpio3 4 0>; ++ input; ++ dir-changeable; ++ }; ++ P9_15 { ++ gpio-name = "P9_15"; ++ gpio = <&gpio2 16 0>; ++ input; ++ dir-changeable; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@12 { ++ target = <&ocp>; ++ __overlay__ { ++ ++ pwm_test_P9_14 { ++ compatible = "pwm_test"; ++ pwms = <&ehrpwm1 0 500000 1>; ++ pwm-names = "PWM_P9_14"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_P9_14>; ++ enabled = <1>; ++ duty = <0>; ++ status = "okay"; ++ }; ++ ++ pwm_test_P9_16 { ++ compatible = "pwm_test"; ++ pwms = <&ehrpwm1 1 500000 1>; ++ pwm-names = "PWM_P9_16"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_P9_16>; ++ enabled = <1>; ++ duty = <0>; ++ status = "okay"; ++ }; ++ ++ pwm_test_P9_42 { ++ compatible = "pwm_test"; ++ pwms = <&ecap0 0 500000 1>; ++ pwm-names = "PWM_P9_42"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_P9_42>; ++ enabled = <1>; ++ duty = <0>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@13 { ++ target = <&ocp>; ++ __overlay__ { ++ /* avoid stupid warning */ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ tscadc { ++ compatible = "ti,ti-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <16>; ++ ti,hwmods = "adc_tsc"; ++ status = "okay"; ++ ++ adc { ++ ti,adc-channels = <4 5 6>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@14 { ++ target = <&spi0>; /* spi0 is numbered correctly */ ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_spi0_pins>; ++ ++ channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "spidev"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++ }; ++ }; ++ ++ fragment@15 { ++ target = <&uart2>; /* really uart1 */ ++ __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_uart1_pins>; ++ }; ++ }; ++}; +-- +1.8.5.3 + diff --git a/common-bsp/recipes-kernel/linux/linux-mainline_3.8.bb b/common-bsp/recipes-kernel/linux/linux-mainline_3.8.bb index e2cfe4a3..6e1f637c 100644 --- a/common-bsp/recipes-kernel/linux/linux-mainline_3.8.bb +++ b/common-bsp/recipes-kernel/linux/linux-mainline_3.8.bb @@ -86,8 +86,7 @@ SRC_URI += " \ file://adc/0016-MFD-ti_tscadc-disable-TSC-control-register-bits-when.patch \ file://adc/0017-IIO-ADC-ti_adc-Fix-1st-sample-read.patch \ file://adc/0018-input-ti_tsc-Enable-shared-IRQ-TSC.patch \ - file://adc/0019-iio-ti_am335x_adc-Add-continuous-sampling-and-trigge.patch \ - file://adc/0020-iio-ti_am335x_adc-Add-IIO-map-interface.patch \ + file://adc/0019-iio-ti_am335x_adc-Add-IIO-map-interface.patch \ file://i2c/0001-pinctrl-pinctrl-single-must-be-initialized-early.patch \ file://i2c/0002-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch \ file://i2c/0003-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch \ @@ -249,6 +248,7 @@ SRC_URI += " \ file://net/0004-beaglebone-TT3201-MCP2515-fixes.patch \ file://net/0005-add-proper-db.txt-for-CRDA.patch \ file://net/0006-mcp251x-add-device-tree-support.patch \ + file://net/0007-net-cpsw-fix-irq_disable-with-threaded-interrupts.patch \ file://drm/0001-am33xx-Add-clock-for-the-lcdc-DRM-driver.patch \ file://drm/0002-drm-small-fix-in-drm_send_vblank_event.patch \ file://drm/0003-drm-cma-add-debugfs-helpers.patch \ @@ -626,6 +626,9 @@ SRC_URI += " \ file://hdmi/0025-drm-tilcdc-fixup-mode-to-workaound-sync-for-tda998x.patch \ file://hdmi/0026-Documentation-for-tilcdc-Devicetree-Bindings.patch \ file://hdmi/0027-drm-tilcdc-adding-more-guards-to-prevent-selecting-i.patch \ + file://audio/0001-Make-the-McASP-code-generic-again-remove-all-hardcod.patch \ + file://audio/0002-ASoc-Davinci-EVM-Config-12MHz-CLK-for-AIC3x-Codec.patch \ + file://audio/0003-ASoc-McASP-Lift-Reset-on-CLK-Dividers-when-RX-TX.patch \ file://resetctrl/0001-boneblack-Remove-default-pinmuxing-for-MMC1.patch \ file://resetctrl/0002-capemgr-Implement-cape-priorities.patch \ file://resetctrl/0003-rstctl-Reset-control-subsystem.patch \ @@ -700,8 +703,37 @@ SRC_URI += " \ file://capes/0015-DT-overlay-for-BeBoPr-with-enable-patch-and-BeagleBo.patch \ file://capes/0016-DT-overlay-for-BeBoPr-Bridge-and-BeagleBone-any-colo.patch \ file://capes/0017-Removed-Whitelist-and-Blacklist-Modes-From-HDMI-Devi.patch \ + file://capes/0018-beaglebone-capes-add-replicape-A2-and-A3-support.patch \ + file://capes/0019-Added-camera-cape-support-for-Beaglebone-Black.patch \ + file://capes/0020-add-argus-ups-cape-support.patch \ + file://capes/0021-Fix-aspect-ratio-issue-of-720p-in-MT9M114-camera-cap.patch \ + file://capes/0022-beaglebone-capes-Added-overlays-for-CBB-Serial-cape.patch \ + file://capes/0023-apply-htu21-patch.patch \ + file://capes/0024-add-support-for-weather-cape-rev-b.patch \ + file://capes/0025-capes-Add-cape-universal-overlay-files-More-details-.patch \ + file://capes/0026-remove-1-wire-gpio-in-weather-cape-rev-B.patch \ + file://capes/0027-cape-add-cape-bone-ibb-00A0.dts.patch \ + file://capes/0028-adds-DTS-for-CryptoCape.patch \ + file://capes/0029-Provides-a-sysfs-interface-to-the-eQEP-hardware-on-t.patch \ + file://capes/0030-capes-add-bone_eqep-from-https-github.com-Teknoman11.patch \ + file://capes/0031-Adding-Logibone-to-cape-support-list.patch \ + file://capes/0032-beaglebone-capes-Added-CBB-Relay-cape-dt-overlay.patch \ + file://capes/0033-Firmware-Update-Replicape-device-tree-overlay-files-.patch \ + file://capes/0034-cape-add-BB-BONE-AUDI-02-00A0-from-http-elinux.org-C.patch \ + file://capes/0035-cape-universaln-remove-P9_31.patch \ + file://proto/0001-add-new-default-pinmux-based-on-Proto-Cape.patch \ + file://logibone/0001-Instering-Logibone-driver-into-kernel.patch \ + file://logibone/0002-Adding-DTS-support-for-Logibone.patch \ file://fixes/0001-sync-don-t-block-the-flusher-thread-waiting-on-IO.patch \ file://fixes/0002-USB-Fix-USB-device-disconnects-on-resume.patch \ + file://fixes/0003-beaglebone-switch-uSD-to-4-bit-mode.patch \ + file://fixes/0004-mmc-omap_hsmmc-clear-status-flags-before-starting-a-.patch \ + file://fixes/0005-uvcvideo-Fix-data-type-for-pan-tilt-control.patch \ + file://fixes/0006-ti_am335x_tsc-touchscreen-jitter-fix.patch \ + file://fixes/0007-omap-RS485-support-by-Michael-Musset.patch \ + file://fixes/0008-deb-pkg-sync-with-v3.14.patch \ + file://machinekit/0001-Add-dir-changeable-property-to-gpio-of-helper.patch \ + file://backports/0001-backport-v3.13.7-tpm_i2c_atmel.c.patch \ file://defconfig \ file://am335x-pm-firmware.bin \ file://logo_linux_clut224.ppm \