* [PATCH 11/14] iio: adc: at91-sama5d2_adc: optimize scan index for diff channels
From: Eugen Hristev @ 2017-12-22 15:07 UTC (permalink / raw)
To: nicolas.ferre, ludovic.desroches, alexandre.belloni, linux-iio,
linux-arm-kernel, devicetree, linux-kernel, jic23, linux-input,
dmitry.torokhov
Cc: Eugen Hristev
In-Reply-To: <1513955241-10985-1-git-send-email-eugen.hristev@microchip.com>
Optimize the scan index for the differential channels. Before, it
was single channel count + index of the first single channel
number of the differential pair. (e.g. 11+0, +2, +4, etc.)
Divide that number by two (since it's always even), and add it up
as a scan index to have consecutive numbered channels in the
index.
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
---
drivers/iio/adc/at91-sama5d2_adc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 7b9febc..9610393 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -209,7 +209,7 @@
.channel = num, \
.channel2 = num2, \
.address = addr, \
- .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
+ .scan_index = (num >> 1) + AT91_SAMA5D2_SINGLE_CHAN_CNT,\
.scan_type = { \
.sign = 's', \
.realbits = 12, \
--
2.7.4
^ permalink raw reply related
* [PATCH 12/14] iio: adc: at91-sama5d2_adc: support for position and pressure channels
From: Eugen Hristev @ 2017-12-22 15:07 UTC (permalink / raw)
To: nicolas.ferre, ludovic.desroches, alexandre.belloni, linux-iio,
linux-arm-kernel, devicetree, linux-kernel, jic23, linux-input,
dmitry.torokhov
Cc: Eugen Hristev
In-Reply-To: <1513955241-10985-1-git-send-email-eugen.hristev@microchip.com>
The ADC IP supports position and pressure measurements for a touchpad
connected on channels 0,1,2,3 for a 4-wire touchscreen with pressure
measurement support.
Using the inkern API, a driver can request a trigger and read the
channel values from the ADC.
The implementation provides a trigger named "touch" which can be
connected to a consumer driver.
Once a driver connects and attaches a pollfunc to this trigger, the
configure trigger callback is called, and then the ADC driver will
initialize pad measurement.
First step is to enable touchscreen 4wire support and enable
pen detect IRQ.
Once a pen is detected, a periodic trigger is setup to trigger every
2 ms (e.g.) and sample the resistive touchscreen values. The trigger poll
is called, and the consumer driver is then woke up, and it can read the
respective channels for the values : X, and Y for position and pressure
channel.
Because only one trigger can be active in hardware in the same time,
while touching the pad, the ADC will block any attempt to use the
triggered buffer. Same, conversions using the software trigger are also
impossible (since the periodic trigger is setup).
If some driver wants to attach while the trigger is in use, it will
also fail.
Once the pen is not detected anymore, the trigger is free for use (hardware
or software trigger, with or without DMA).
Channels 0,1,2 and 3 are unavailable if a touchscreen is enabled.
Some parts of this patch are based on initial original work by
Mohamed Jamsheeth Hajanajubudeen and Bandaru Venkateswara Swamy
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
---
drivers/iio/adc/at91-sama5d2_adc.c | 455 ++++++++++++++++++++++++++++++++++++-
1 file changed, 446 insertions(+), 9 deletions(-)
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 9610393..79eb197 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -102,14 +102,26 @@
#define AT91_SAMA5D2_LCDR 0x20
/* Interrupt Enable Register */
#define AT91_SAMA5D2_IER 0x24
+/* Interrupt Enable Register - TS X measurement ready */
+#define AT91_SAMA5D2_IER_XRDY BIT(20)
+/* Interrupt Enable Register - TS Y measurement ready */
+#define AT91_SAMA5D2_IER_YRDY BIT(21)
+/* Interrupt Enable Register - TS pressure measurement ready */
+#define AT91_SAMA5D2_IER_PRDY BIT(22)
/* Interrupt Enable Register - general overrun error */
#define AT91_SAMA5D2_IER_GOVRE BIT(25)
+/* Interrupt Enable Register - Pen detect */
+#define AT91_SAMA5D2_IER_PEN BIT(29)
+/* Interrupt Enable Register - No pen detect */
+#define AT91_SAMA5D2_IER_NOPEN BIT(30)
/* Interrupt Disable Register */
#define AT91_SAMA5D2_IDR 0x28
/* Interrupt Mask Register */
#define AT91_SAMA5D2_IMR 0x2c
/* Interrupt Status Register */
#define AT91_SAMA5D2_ISR 0x30
+/* Interrupt Status Register - Pen touching sense status */
+#define AT91_SAMA5D2_ISR_PENS BIT(31)
/* Last Channel Trigger Mode Register */
#define AT91_SAMA5D2_LCTMR 0x34
/* Last Channel Compare Window Register */
@@ -131,8 +143,37 @@
#define AT91_SAMA5D2_CDR0 0x50
/* Analog Control Register */
#define AT91_SAMA5D2_ACR 0x94
+/* Analog Control Register - Pen detect sensitivity mask */
+#define AT91_SAMA5D2_ACR_PENDETSENS_MASK GENMASK(0, 1)
/* Touchscreen Mode Register */
#define AT91_SAMA5D2_TSMR 0xb0
+/* Touchscreen Mode Register - No touch mode */
+#define AT91_SAMA5D2_TSMR_TSMODE_NONE 0
+/* Touchscreen Mode Register - 4 wire screen, no pressure measurement */
+#define AT91_SAMA5D2_TSMR_TSMODE_4WIRE_NO_PRESS 1
+/* Touchscreen Mode Register - 4 wire screen, pressure measurement */
+#define AT91_SAMA5D2_TSMR_TSMODE_4WIRE_PRESS 2
+/* Touchscreen Mode Register - 5 wire screen */
+#define AT91_SAMA5D2_TSMR_TSMODE_5WIRE 3
+/* Touchscreen Mode Register - Average samples mask */
+#define AT91_SAMA5D2_TSMR_TSAV_MASK (3 << 4)
+/* Touchscreen Mode Register - Average samples */
+#define AT91_SAMA5D2_TSMR_TSAV(x) ((x) << 4)
+/* Touchscreen Mode Register - Touch/trigger frequency ratio mask */
+#define AT91_SAMA5D2_TSMR_TSFREQ_MASK (0xf << 8)
+/* Touchscreen Mode Register - Touch/trigger freqency ratio */
+#define AT91_SAMA5D2_TSMR_TSFREQ(x) ((x) << 8)
+/* Touchscreen Mode Register - Pen Debounce Time mask */
+#define AT91_SAMA5D2_TSMR_PENDBC_MASK (0xf << 28)
+/* Touchscreen Mode Register - Pen Debounce Time */
+#define AT91_SAMA5D2_TSMR_PENDBC(x) ((x) << 28)
+/* Touchscreen Mode Register - No DMA for touch measurements */
+#define AT91_SAMA5D2_TSMR_NOTSDMA BIT(22)
+/* Touchscreen Mode Register - Disable pen detection */
+#define AT91_SAMA5D2_TSMR_PENDET_DIS (0 << 24)
+/* Touchscreen Mode Register - Enable pen detection */
+#define AT91_SAMA5D2_TSMR_PENDET_ENA BIT(24)
+
/* Touchscreen X Position Register */
#define AT91_SAMA5D2_XPOSR 0xb4
/* Touchscreen Y Position Register */
@@ -151,7 +192,12 @@
#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
/* Trigger Mode external trigger any edge */
#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
-
+/* Trigger Mode internal periodic */
+#define AT91_SAMA5D2_TRGR_TRGMOD_PERIODIC 5
+/* Trigger Mode - trigger period mask */
+#define AT91_SAMA5D2_TRGR_TRGPER_MASK (0xffff << 16)
+/* Trigger Mode - trigger period */
+#define AT91_SAMA5D2_TRGR_TRGPER(x) ((x) << 16)
/* Correction Select Register */
#define AT91_SAMA5D2_COSR 0xd0
/* Correction Value Register */
@@ -169,6 +215,21 @@
#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
+#define AT91_SAMA5D2_TIMESTAMP_CHAN_IDX (AT91_SAMA5D2_SINGLE_CHAN_CNT + \
+ AT91_SAMA5D2_DIFF_CHAN_CNT + 1)
+
+#define AT91_SAMA5D2_TOUCH_X_CHAN_IDX (AT91_SAMA5D2_TIMESTAMP_CHAN_IDX + 1)
+#define AT91_SAMA5D2_TOUCH_Y_CHAN_IDX (AT91_SAMA5D2_TOUCH_X_CHAN_IDX + 1)
+#define AT91_SAMA5D2_TOUCH_P_CHAN_IDX (AT91_SAMA5D2_TOUCH_Y_CHAN_IDX + 1)
+
+#define TOUCH_SAMPLE_PERIOD_US 2000 /* 2ms */
+#define TOUCH_PEN_DETECT_DEBOUNCE_US 200
+
+#define XYZ_MASK GENMASK(11, 0)
+
+#define MAX_POS_BITS 12
+
+#define AT91_ADC_TOUCH_TRIG_SHORTNAME "touch"
/*
* Maximum number of bytes to hold conversion from all channels
* without the timestamp.
@@ -222,6 +283,37 @@
.indexed = 1, \
}
+#define AT91_SAMA5D2_CHAN_TOUCH(num, name, mod) \
+ { \
+ .type = IIO_POSITION, \
+ .modified = 1, \
+ .channel = num, \
+ .channel2 = mod, \
+ .scan_index = num, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ }, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+ .datasheet_name = name, \
+ }
+#define AT91_SAMA5D2_CHAN_PRESSURE(num, name) \
+ { \
+ .type = IIO_PRESSURE, \
+ .channel = num, \
+ .scan_index = num, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ }, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+ .datasheet_name = name, \
+ }
+
#define at91_adc_readl(st, reg) readl_relaxed(st->base + reg)
#define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg)
@@ -239,6 +331,20 @@ struct at91_adc_trigger {
};
/**
+ * at91_adc_touch - at91-sama5d2 touchscreen information struct
+ * @trig: hold the start timestamp of dma operation
+ * @sample_period_val: the value for periodic trigger interval
+ * @touching: is the pen touching the screen or not
+ * @x_pos: temporary placeholder for pressure computation
+ */
+struct at91_adc_touch {
+ struct iio_trigger *trig;
+ u16 sample_period_val;
+ bool touching;
+ u32 x_pos;
+};
+
+/**
* at91_adc_dma - at91-sama5d2 dma information struct
* @dma_chan: the dma channel acquired
* @rx_buf: dma coherent allocated area
@@ -267,18 +373,22 @@ struct at91_adc_state {
struct regulator *reg;
struct regulator *vref;
int vref_uv;
+ unsigned int current_sample_rate;
struct iio_trigger *trig;
const struct at91_adc_trigger *selected_trig;
const struct iio_chan_spec *chan;
bool conversion_done;
u32 conversion_value;
+ bool touch_requested;
struct at91_adc_soc_info soc_info;
wait_queue_head_t wq_data_available;
struct at91_adc_dma dma_st;
+ struct at91_adc_touch touch_st;
u16 buffer[AT91_BUFFER_MAX_HWORDS];
/*
* lock to prevent concurrent 'single conversion' requests through
- * sysfs.
+ * sysfs. Also protects when enabling or disabling touchscreen
+ * producer mode and checking if this mode is enabled or not.
*/
struct mutex lock;
};
@@ -310,6 +420,7 @@ static const struct at91_adc_trigger at91_adc_trigger_list[] = {
},
};
+/* channel order is not subject to change. inkern consumers rely on this */
static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
@@ -329,10 +440,103 @@ static const struct iio_chan_spec at91_adc_channels[] = {
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
- IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
- + AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
+ IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_TIMESTAMP_CHAN_IDX),
+ AT91_SAMA5D2_CHAN_TOUCH(AT91_SAMA5D2_TOUCH_X_CHAN_IDX, "x", IIO_MOD_X),
+ AT91_SAMA5D2_CHAN_TOUCH(AT91_SAMA5D2_TOUCH_Y_CHAN_IDX, "y", IIO_MOD_Y),
+ AT91_SAMA5D2_CHAN_PRESSURE(AT91_SAMA5D2_TOUCH_P_CHAN_IDX, "pressure"),
};
+static int at91_adc_configure_touch(struct at91_adc_state *st, bool state)
+{
+ u32 clk_khz = st->current_sample_rate / 1000;
+ int i = 0;
+ u16 pendbc;
+ u32 tsmr, acr;
+
+ if (!state) {
+ /* disabling touch IRQs and setting mode to no touch enabled */
+ at91_adc_writel(st, AT91_SAMA5D2_IDR,
+ AT91_SAMA5D2_IER_PEN | AT91_SAMA5D2_IER_NOPEN);
+ at91_adc_writel(st, AT91_SAMA5D2_TSMR, 0);
+ return 0;
+ }
+ /*
+ * debounce time is in microseconds, we need it in milliseconds to
+ * multiply with kilohertz, so, divide by 1000, but after the multiply.
+ * round up to make sure pendbc is at least 1
+ */
+ pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * clk_khz / 1000, 1);
+
+ /* get the required exponent */
+ while (pendbc >> i++)
+ ;
+
+ pendbc = i;
+
+ tsmr = AT91_SAMA5D2_TSMR_TSMODE_4WIRE_PRESS;
+
+ tsmr |= AT91_SAMA5D2_TSMR_TSAV(1) & AT91_SAMA5D2_TSMR_TSAV_MASK;
+ tsmr |= AT91_SAMA5D2_TSMR_PENDBC(pendbc) &
+ AT91_SAMA5D2_TSMR_PENDBC_MASK;
+ tsmr |= AT91_SAMA5D2_TSMR_NOTSDMA;
+ tsmr |= AT91_SAMA5D2_TSMR_PENDET_ENA;
+ tsmr |= AT91_SAMA5D2_TSMR_TSFREQ(1) & AT91_SAMA5D2_TSMR_TSFREQ_MASK;
+
+ at91_adc_writel(st, AT91_SAMA5D2_TSMR, tsmr);
+
+ acr = at91_adc_readl(st, AT91_SAMA5D2_ACR);
+ acr &= ~AT91_SAMA5D2_ACR_PENDETSENS_MASK;
+ acr |= 0x02 & AT91_SAMA5D2_ACR_PENDETSENS_MASK;
+ at91_adc_writel(st, AT91_SAMA5D2_ACR, acr);
+
+ /* Sample Period Time = (TRGPER + 1) / ADCClock */
+ st->touch_st.sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US *
+ clk_khz / 1000) - 1, 1);
+ /* enable pen detect IRQ */
+ at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_PEN);
+
+ return 0;
+}
+
+static int at91_adc_touch_trigger_validate_device(struct iio_trigger *trig,
+ struct iio_dev *indio_dev)
+{
+ /* the touch trigger cannot be used with a buffer */
+ return -EBUSY;
+}
+
+static int at91_adc_configure_touch_trigger(struct iio_trigger *trig,
+ bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio_dev);
+ int ret = 0;
+
+ /*
+ * If we configure this with the IRQ enabled, the pen detected IRQ
+ * might fire before we finish setting all up, and the IRQ handler
+ * might misbehave. Better to reenable the IRQ after we are done
+ */
+ disable_irq_nosync(st->irq);
+
+ mutex_lock(&st->lock);
+ if (state) {
+ ret = iio_buffer_enabled(indio_dev);
+ if (ret) {
+ dev_dbg(&indio_dev->dev, "trigger is currently in use\n");
+ ret = -EBUSY;
+ goto configure_touch_unlock_exit;
+ }
+ }
+ at91_adc_configure_touch(st, state);
+ st->touch_requested = state;
+
+configure_touch_unlock_exit:
+ enable_irq(st->irq);
+ mutex_unlock(&st->lock);
+ return ret;
+}
+
static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
{
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
@@ -390,12 +594,27 @@ static int at91_adc_reenable_trigger(struct iio_trigger *trig)
return 0;
}
+static int at91_adc_reenable_touch_trigger(struct iio_trigger *trig)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio);
+
+ enable_irq(st->irq);
+
+ return 0;
+}
static const struct iio_trigger_ops at91_adc_trigger_ops = {
.set_trigger_state = &at91_adc_configure_trigger,
.try_reenable = &at91_adc_reenable_trigger,
.validate_device = iio_trigger_validate_own_device,
};
+static const struct iio_trigger_ops at91_adc_touch_trigger_ops = {
+ .set_trigger_state = &at91_adc_configure_touch_trigger,
+ .try_reenable = &at91_adc_reenable_touch_trigger,
+ .validate_device = &at91_adc_touch_trigger_validate_device,
+};
+
static int at91_adc_dma_size_done(struct at91_adc_state *st)
{
struct dma_tx_state state;
@@ -490,6 +709,23 @@ static int at91_adc_dma_start(struct iio_dev *indio_dev)
return 0;
}
+static int at91_adc_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct at91_adc_state *st = iio_priv(indio_dev);
+ int ret;
+
+ /* have to make sure nobody is requesting the trigger right now */
+ mutex_lock(&st->lock);
+ ret = st->touch_requested;
+ mutex_unlock(&st->lock);
+
+ /*
+ * if the trigger is used by the touchscreen,
+ * we must return an error
+ */
+ return ret ? -EBUSY : 0;
+}
+
static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
{
int ret;
@@ -538,6 +774,7 @@ static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
}
static const struct iio_buffer_setup_ops at91_buffer_setup_ops = {
+ .preenable = &at91_adc_buffer_preenable,
.postenable = &at91_adc_buffer_postenable,
.predisable = &at91_adc_buffer_predisable,
};
@@ -555,7 +792,11 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
trig->dev.parent = indio->dev.parent;
iio_trigger_set_drvdata(trig, indio);
- trig->ops = &at91_adc_trigger_ops;
+
+ if (strcmp(trigger_name, AT91_ADC_TOUCH_TRIG_SHORTNAME))
+ trig->ops = &at91_adc_trigger_ops;
+ else
+ trig->ops = &at91_adc_touch_trigger_ops;
ret = devm_iio_trigger_register(&indio->dev, trig);
if (ret)
@@ -571,7 +812,16 @@ static int at91_adc_trigger_init(struct iio_dev *indio)
st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
if (IS_ERR(st->trig)) {
dev_err(&indio->dev,
- "could not allocate trigger\n");
+ "could not allocate trigger %s\n",
+ st->selected_trig->name);
+ return PTR_ERR(st->trig);
+ }
+
+ st->touch_st.trig = at91_adc_allocate_trigger(indio,
+ AT91_ADC_TOUCH_TRIG_SHORTNAME);
+ if (IS_ERR(st->trig)) {
+ dev_err(&indio->dev, "could not allocate trigger"
+ AT91_ADC_TOUCH_TRIG_SHORTNAME "\n");
return PTR_ERR(st->trig);
}
@@ -703,6 +953,8 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
freq, startup, prescal);
+
+ st->current_sample_rate = freq;
}
static unsigned at91_adc_get_sample_freq(struct at91_adc_state *st)
@@ -718,23 +970,77 @@ static unsigned at91_adc_get_sample_freq(struct at91_adc_state *st)
return f_adc;
}
+static irqreturn_t at91_adc_pen_detect_interrupt(struct at91_adc_state *st)
+{
+ at91_adc_writel(st, AT91_SAMA5D2_IDR, AT91_SAMA5D2_IER_PEN);
+ at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_NOPEN |
+ AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY |
+ AT91_SAMA5D2_IER_PRDY);
+ at91_adc_writel(st, AT91_SAMA5D2_TRGR,
+ AT91_SAMA5D2_TRGR_TRGMOD_PERIODIC |
+ AT91_SAMA5D2_TRGR_TRGPER(st->touch_st.sample_period_val));
+ st->touch_st.touching = true;
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t at91_adc_no_pen_detect_interrupt(struct at91_adc_state *st)
+{
+ at91_adc_writel(st, AT91_SAMA5D2_TRGR, 0);
+ at91_adc_writel(st, AT91_SAMA5D2_IDR, AT91_SAMA5D2_IER_NOPEN |
+ AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY |
+ AT91_SAMA5D2_IER_PRDY);
+ st->touch_st.touching = false;
+
+ disable_irq_nosync(st->irq);
+ iio_trigger_poll(st->touch_st.trig);
+
+ at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_PEN);
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t at91_adc_interrupt(int irq, void *private)
{
struct iio_dev *indio = private;
struct at91_adc_state *st = iio_priv(indio);
u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
+ u32 rdy_mask = AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY |
+ AT91_SAMA5D2_IER_PRDY;
if (!(status & imr))
return IRQ_NONE;
- if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) {
+ if (st->touch_requested && (status & AT91_SAMA5D2_IER_PEN)) {
+ /* pen detected IRQ */
+ return at91_adc_pen_detect_interrupt(st);
+ } else if (st->touch_requested && (status & AT91_SAMA5D2_IER_NOPEN)) {
+ /* nopen detected IRQ */
+ return at91_adc_no_pen_detect_interrupt(st);
+ } else if (st->touch_requested && (status & AT91_SAMA5D2_ISR_PENS) &&
+ ((status & rdy_mask) == rdy_mask)) {
+ /* periodic trigger IRQ - during pen sense */
+ disable_irq_nosync(irq);
+ iio_trigger_poll(st->touch_st.trig);
+ } else if ((st->touch_requested && (status & AT91_SAMA5D2_ISR_PENS))) {
+ /*
+ * touching, but the measurements are not ready yet.
+ * read and ignore.
+ */
+ status = at91_adc_readl(st, AT91_SAMA5D2_XPOSR);
+ status = at91_adc_readl(st, AT91_SAMA5D2_YPOSR);
+ status = at91_adc_readl(st, AT91_SAMA5D2_PRESSR);
+ } else if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) {
+ /* buffered trigger without DMA */
disable_irq_nosync(irq);
iio_trigger_poll(indio->trig);
} else if (iio_buffer_enabled(indio) && st->dma_st.dma_chan) {
+ /* buffered trigger with DMA - should not happen */
disable_irq_nosync(irq);
WARN(true, "Unexpected irq occurred\n");
} else if (!iio_buffer_enabled(indio)) {
+ /* software requested conversion */
st->conversion_value = at91_adc_readl(st, st->chan->address);
st->conversion_done = true;
wake_up_interruptible(&st->wq_data_available);
@@ -742,6 +1048,96 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
return IRQ_HANDLED;
}
+static u32 at91_adc_touch_x_pos(struct at91_adc_state *st)
+{
+ u32 xscale, val;
+ u32 x, xpos;
+
+ /* x position = (x / xscale) * max, max = 2^MAX_POS_BITS - 1 */
+ val = at91_adc_readl(st, AT91_SAMA5D2_XPOSR);
+ if (!val)
+ dev_dbg(&iio_priv_to_dev(st)->dev, "x_pos is 0\n");
+
+ xpos = val & XYZ_MASK;
+ x = (xpos << MAX_POS_BITS) - xpos;
+ xscale = (val >> 16) & XYZ_MASK;
+ if (xscale == 0) {
+ dev_err(&iio_priv_to_dev(st)->dev, "xscale is 0\n");
+ return 0;
+ }
+ x /= xscale;
+ st->touch_st.x_pos = x;
+
+ return x;
+}
+
+static u32 at91_adc_touch_y_pos(struct at91_adc_state *st)
+{
+ u32 yscale, val;
+ u32 y, ypos;
+
+ /* y position = (y / yscale) * max, max = 2^MAX_POS_BITS - 1 */
+ val = at91_adc_readl(st, AT91_SAMA5D2_YPOSR);
+ ypos = val & XYZ_MASK;
+ y = (ypos << MAX_POS_BITS) - ypos;
+ yscale = (val >> 16) & XYZ_MASK;
+
+ if (yscale == 0)
+ return 0;
+
+ y /= yscale;
+
+ return y;
+}
+
+static u32 at91_adc_touch_pressure(struct at91_adc_state *st)
+{
+ u32 val, z1, z2;
+ u32 pres;
+ u32 rxp = 1;
+ u32 factor = 1000;
+
+ /* calculate the pressure */
+ val = at91_adc_readl(st, AT91_SAMA5D2_PRESSR);
+ z1 = val & XYZ_MASK;
+ z2 = (val >> 16) & XYZ_MASK;
+
+ if (z1 != 0)
+ pres = rxp * (st->touch_st.x_pos * factor / 1024) *
+ (z2 * factor / z1 - factor) /
+ factor;
+ else
+ pres = 0xFFFFFFFF; /* no pen contact */
+
+ return pres;
+}
+
+static int at91_adc_read_position(struct at91_adc_state *st, int chan, int *val)
+{
+ if (!st->touch_st.touching)
+ return -ENODATA;
+ if (chan == AT91_SAMA5D2_TOUCH_X_CHAN_IDX)
+ *val = at91_adc_touch_x_pos(st);
+ else if (chan == AT91_SAMA5D2_TOUCH_Y_CHAN_IDX)
+ *val = at91_adc_touch_y_pos(st);
+ else
+ return -ENODATA;
+
+ return IIO_VAL_INT;
+}
+
+static int at91_adc_read_pressure(struct at91_adc_state *st, int chan, int *val)
+{
+ if (!st->touch_st.touching)
+ return -ENODATA;
+ if (chan == AT91_SAMA5D2_TOUCH_P_CHAN_IDX)
+ *val = at91_adc_touch_pressure(st);
+ else
+ return -ENODATA;
+
+ return IIO_VAL_INT;
+}
+
static int at91_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
@@ -752,11 +1148,38 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
+ mutex_lock(&st->lock);
+
+ if (chan->type == IIO_POSITION) {
+ ret = at91_adc_read_position(st, chan->channel, val);
+ mutex_unlock(&st->lock);
+ return ret;
+ }
+ if (chan->type == IIO_PRESSURE) {
+ ret = at91_adc_read_pressure(st, chan->channel, val);
+ mutex_unlock(&st->lock);
+ return ret;
+ }
+ /* if we using touch, channels 0, 1, 2, 3 are unavailable */
+ if (st->touch_requested && chan->channel <= 3) {
+ mutex_unlock(&st->lock);
+ return -EBUSY;
+ }
+ /*
+ * if we have the periodic trigger set up, we can't use
+ * software trigger either.
+ */
+ if (st->touch_st.touching) {
+ mutex_unlock(&st->lock);
+ return -ENODATA;
+ }
+
/* we cannot use software trigger if hw trigger enabled */
ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
+ if (ret) {
+ mutex_unlock(&st->lock);
return ret;
- mutex_lock(&st->lock);
+ }
st->chan = chan;
@@ -785,6 +1208,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel));
at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
+ /*
+ * It is possible that after this conversion, we reuse these
+ * channels for the touchscreen. So, reset the COR now.
+ */
+ at91_adc_writel(st, AT91_SAMA5D2_COR, 0);
/* Needed to ACK the DRDY interruption */
at91_adc_readl(st, AT91_SAMA5D2_LCDR);
@@ -1180,6 +1608,10 @@ static int at91_adc_remove(struct platform_device *pdev)
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct at91_adc_state *st = iio_priv(indio_dev);
+ mutex_lock(&st->lock);
+ devm_iio_trigger_unregister(&indio_dev->dev, st->touch_st.trig);
+ mutex_unlock(&st->lock);
+
if (st->selected_trig->hw_trig)
devm_iio_trigger_unregister(&indio_dev->dev, st->trig);
@@ -1245,6 +1677,11 @@ static __maybe_unused int at91_adc_resume(struct device *dev)
if (iio_buffer_enabled(indio_dev))
at91_adc_configure_trigger(st->trig, true);
+ mutex_lock(&st->lock);
+ if (st->touch_requested)
+ at91_adc_configure_touch_trigger(st->touch_st.trig, true);
+ mutex_unlock(&st->lock);
+
return 0;
vref_disable_resume:
--
2.7.4
^ permalink raw reply related
* [PATCH 13/14] input: touchscreen: sama5d2_rts: SAMA5D2 Resistive touchscreen driver
From: Eugen Hristev @ 2017-12-22 15:07 UTC (permalink / raw)
To: nicolas.ferre, ludovic.desroches, alexandre.belloni, linux-iio,
linux-arm-kernel, devicetree, linux-kernel, jic23, linux-input,
dmitry.torokhov
Cc: Eugen Hristev
In-Reply-To: <1513955241-10985-1-git-send-email-eugen.hristev@microchip.com>
This is the implementation of the Microchip SAMA5D2 SOC resistive
touchscreen driver.
The driver registers an input device and connects to the give IIO device
from devicetree. It requires an IIO trigger (acting as a consumer) and
three IIO channels : one for X position, one for Y position and one
for pressure.
It the reports the values to the input subsystem.
Some parts of this driver are based on the initial original work by
Mohamed Jamsheeth Hajanajubudeen and Bandaru Venkateswara Swamy
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
---
drivers/input/touchscreen/Kconfig | 13 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/sama5d2_rts.c | 287 ++++++++++++++++++++++++++++++++
3 files changed, 301 insertions(+)
create mode 100644 drivers/input/touchscreen/sama5d2_rts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 64b30fe..db8f541 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -126,6 +126,19 @@ config TOUCHSCREEN_ATMEL_MXT_T37
Say Y here if you want support to output data from the T37
Diagnostic Data object using a V4L device.
+config TOUCHSCREEN_SAMA5D2
+ tristate "Microchip SAMA5D2 resistive touchscreen support"
+ depends on ARCH_AT91
+ depends on AT91_SAMA5D2_ADC
+ help
+ Say Y here if you have 4-wire touchscreen connected
+ to ADC Controller on your SAMA5D2 Microchip SoC.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sama5d2_rts.
+
config TOUCHSCREEN_AUO_PIXCIR
tristate "AUO in-cell touchscreen using Pixcir ICs"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 850c156..9a2772e 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
+obj-$(CONFIG_TOUCHSCREEN_SAMA5D2) += sama5d2_rts.o
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8318) += chipone_icn8318.o
diff --git a/drivers/input/touchscreen/sama5d2_rts.c b/drivers/input/touchscreen/sama5d2_rts.c
new file mode 100644
index 0000000..e2ae413
--- /dev/null
+++ b/drivers/input/touchscreen/sama5d2_rts.c
@@ -0,0 +1,287 @@
+/*
+ * Microchip resistive touchscreen (RTS) driver for SAMA5D2.
+ *
+ * Copyright (C) 2017 Microchip Technology,
+ * Author: Eugen Hristev <eugen.hristev@microchip.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+#include <linux/input.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define DRIVER_NAME "sama5d2_rts"
+#define MAX_POS_MASK GENMASK(11, 0)
+#define AT91_RTS_DEFAULT_PRESSURE_THRESHOLD 10000
+
+/**
+ * at91_rts - at91 resistive touchscreen information struct
+ * @input: the input device structure that we register
+ * @chan_x: X channel to IIO device to get position on X axis
+ * @chan_y: Y channel to IIO device to get position on Y axis
+ * @chan_pressure: pressure channel to IIO device to get pressure
+ * @trig: trigger to IIO device to register to for polling
+ * @rts_pf: pollfunc for the trigger to be called by IIO dev
+ * @pressure_threshold: number representing the threshold for the pressure
+ * @adc_connected: to know if adc device is connected
+ * @workq: to defer computations to this work queue for reporting
+ */
+struct at91_rts {
+ struct input_dev *input;
+ struct iio_channel *chan_x, *chan_y, *chan_pressure;
+ struct iio_trigger *trig;
+ struct iio_poll_func *rts_pf;
+ u32 pressure_threshold;
+ bool adc_connected;
+ struct work_struct workq;
+};
+
+static irqreturn_t at91_rts_trigger_handler(int irq, void *p)
+{
+ struct at91_rts *st = ((struct iio_poll_func *)p)->p;
+
+ schedule_work(&st->workq);
+
+ return IRQ_HANDLED;
+}
+
+static void at91_rts_workq_handler(struct work_struct *workq)
+{
+ struct at91_rts *st = container_of(workq, struct at91_rts, workq);
+ unsigned int x, y, press;
+ int ret;
+
+ /* read the channels, if all good, report touch */
+ ret = iio_read_channel_raw(st->chan_x, &x);
+ if (ret < 0)
+ goto at91_rts_workq_handler_end_touch;
+
+ ret = iio_read_channel_raw(st->chan_y, &y);
+ if (ret < 0)
+ goto at91_rts_workq_handler_end_touch;
+
+ ret = iio_read_channel_raw(st->chan_pressure, &press);
+ if (ret < 0)
+ goto at91_rts_workq_handler_end_touch;
+
+ /* if pressure too low, don't report */
+ if (press > st->pressure_threshold)
+ goto at91_rts_workq_handler_exit;
+
+ input_report_abs(st->input, ABS_X, x);
+ input_report_abs(st->input, ABS_Y, y);
+ input_report_abs(st->input, ABS_PRESSURE, press);
+ input_report_key(st->input, BTN_TOUCH, 1);
+ input_sync(st->input);
+
+ iio_trigger_notify_done(st->trig);
+ return;
+
+at91_rts_workq_handler_end_touch:
+ /* report end of touch */
+ input_report_key(st->input, BTN_TOUCH, 0);
+ input_sync(st->input);
+at91_rts_workq_handler_exit:
+ iio_trigger_notify_done(st->trig);
+}
+
+static int at91_rts_open(struct input_dev *dev)
+{
+ int ret;
+ struct at91_rts *st = input_get_drvdata(dev);
+
+ /* avoid multiple initialization in case touchscreen is opened again */
+ if (st->adc_connected)
+ return 0;
+
+ /*
+ * First, look for the channels. It is possible that the ADC device
+ * did not probe yet, but we already probed, so we returning probe defer
+ * doesn't make much sense.
+ */
+ st->chan_x = iio_channel_get(dev->dev.parent, "x");
+ if (IS_ERR_OR_NULL(st->chan_x)) {
+ dev_err(dev->dev.parent, "cannot get X channel from ADC");
+ ret = PTR_ERR(st->chan_x);
+ goto at91_rts_open_free_chan;
+ }
+
+ st->chan_y = iio_channel_get(dev->dev.parent, "y");
+ if (IS_ERR_OR_NULL(st->chan_y)) {
+ dev_err(dev->dev.parent, "cannot get Y channel from ADC");
+ ret = PTR_ERR(st->chan_y);
+ goto at91_rts_open_free_chan;
+ }
+
+ st->chan_pressure = iio_channel_get(dev->dev.parent, "pressure");
+ if (IS_ERR_OR_NULL(st->chan_pressure)) {
+ dev_err(dev->dev.parent, "cannot get pressure channel from ADC");
+ ret = PTR_ERR(st->chan_pressure);
+ goto at91_rts_open_free_chan;
+ }
+
+ /* look for the trigger in device tree */
+ st->trig = iio_trigger_find(dev->dev.parent, NULL);
+ if (IS_ERR_OR_NULL(st->trig)) {
+ dev_err(dev->dev.parent, "cannot get trigger from ADC");
+ ret = PTR_ERR(st->trig);
+ goto at91_rts_open_free_chan;
+ }
+
+ /* allocate a pollfunc for the trigger */
+ st->rts_pf = iio_alloc_pollfunc(at91_rts_trigger_handler, NULL,
+ IRQF_ONESHOT, NULL,
+ dev->dev.parent->of_node->name);
+ if (!st->rts_pf) {
+ ret = -ENOMEM;
+ dev_err(dev->dev.parent, "cannot allocate trigger pollfunc");
+ goto at91_rts_open_free_chan;
+ }
+
+ iio_pollfunc_set_private_data(st->rts_pf, st);
+
+ /*
+ * Attach the pollfunc to the trigger. This will also call the
+ * configure function to enable the trigger
+ */
+ ret = iio_trigger_attach_poll_func(st->trig, st->rts_pf);
+ if (ret)
+ goto at91_rts_open_dealloc_pf;
+
+ dev_dbg(dev->dev.parent, "channels found, attached to trigger");
+
+ st->adc_connected = true;
+ return 0;
+
+at91_rts_open_dealloc_pf:
+ iio_dealloc_pollfunc(st->rts_pf);
+at91_rts_open_free_chan:
+ if (!IS_ERR_OR_NULL(st->chan_x))
+ iio_channel_release(st->chan_x);
+ if (!IS_ERR_OR_NULL(st->chan_y))
+ iio_channel_release(st->chan_y);
+ if (!IS_ERR_OR_NULL(st->chan_pressure))
+ iio_channel_release(st->chan_pressure);
+ /*
+ * Avoid keeping old values in channel pointers. in case some channel
+ * failed and we reopen them, and now fail, we will have invalid values
+ * to release. So write them as NULL now.
+ */
+ st->chan_x = NULL;
+ st->chan_y = NULL;
+ st->chan_pressure = NULL;
+ return ret;
+}
+
+static void at91_rts_close(struct input_dev *dev)
+{
+ struct at91_rts *st = input_get_drvdata(dev);
+
+ if (!st->adc_connected)
+ return;
+
+ iio_trigger_detach_poll_func(st->trig, st->rts_pf);
+ iio_dealloc_pollfunc(st->rts_pf);
+
+ if (!IS_ERR_OR_NULL(st->chan_x))
+ iio_channel_release(st->chan_x);
+ if (!IS_ERR_OR_NULL(st->chan_y))
+ iio_channel_release(st->chan_y);
+ if (!IS_ERR_OR_NULL(st->chan_pressure))
+ iio_channel_release(st->chan_pressure);
+
+ st->adc_connected = false;
+}
+
+static int at91_rts_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct at91_rts *st;
+ struct input_dev *input;
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+
+ st = devm_kzalloc(dev, sizeof(struct at91_rts), GFP_KERNEL);
+ if (!st)
+ return -ENOMEM;
+ st->adc_connected = false;
+
+ INIT_WORK(&st->workq, at91_rts_workq_handler);
+
+ input = devm_input_allocate_device(dev);
+ if (!input) {
+ dev_err(dev, "failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ ret = of_property_read_u32(node, "microchip,pressure-threshold",
+ &st->pressure_threshold);
+ if (ret < 0) {
+ dev_dbg(dev, "can't get touchscreen pressure threshold property.\n");
+ st->pressure_threshold = AT91_RTS_DEFAULT_PRESSURE_THRESHOLD;
+ }
+
+ input->name = DRIVER_NAME;
+ input->id.bustype = BUS_HOST;
+ input->dev.parent = &pdev->dev;
+ input->open = at91_rts_open;
+ input->close = at91_rts_close;
+
+ input_set_abs_params(input, ABS_X, 0, MAX_POS_MASK - 1, 0, 0);
+ input_set_abs_params(input, ABS_Y, 0, MAX_POS_MASK, 0, 0);
+ input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0);
+
+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ st->input = input;
+ input_set_drvdata(input, st);
+
+ ret = input_register_device(input);
+ if (ret) {
+ dev_err(dev, "failed to register input device: %d", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, st);
+
+ dev_info(dev, "probed successfully\n");
+ return 0;
+}
+
+static int at91_rts_remove(struct platform_device *pdev)
+{
+ struct at91_rts *st = platform_get_drvdata(pdev);
+
+ input_unregister_device(st->input);
+
+ return 0;
+}
+
+static const struct of_device_id at91_rts_of_match[] = {
+ {
+ .compatible = "microchip,sama5d2-resistive-touch",
+ }, {
+ /* sentinel */
+ },
+};
+MODULE_DEVICE_TABLE(of, at91_rts_of_match);
+
+static struct platform_driver atmel_rts_driver = {
+ .probe = at91_rts_probe,
+ .remove = at91_rts_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = of_match_ptr(at91_rts_of_match),
+ },
+};
+
+module_platform_driver(atmel_rts_driver);
+
+MODULE_AUTHOR("Eugen Hristev <eugen.hristev@microchip.com>");
+MODULE_DESCRIPTION("Microchip SAMA5D2 Resistive Touch Driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* [PATCH 14/14] ARM: dts: at91: sama5d2: Add resistive touch device
From: Eugen Hristev @ 2017-12-22 15:07 UTC (permalink / raw)
To: nicolas.ferre, ludovic.desroches, alexandre.belloni, linux-iio,
linux-arm-kernel, devicetree, linux-kernel, jic23, linux-input,
dmitry.torokhov
Cc: Eugen Hristev
In-Reply-To: <1513955241-10985-1-git-send-email-eugen.hristev@microchip.com>
Add the resistive touchscreen device, and the cell numbers to the
ADC device.
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
---
arch/arm/boot/dts/sama5d2.dtsi | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index b1a26b4..30b3797 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -402,7 +402,6 @@
compatible = "atmel,hlcdc-display-controller";
#address-cells = <1>;
#size-cells = <0>;
-
port@0 {
#address-cells = <1>;
#size-cells = <0>;
@@ -1431,6 +1430,17 @@
atmel,max-sample-rate-hz = <20000000>;
atmel,startup-time-ms = <4>;
atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
+ #io-channel-cells = <1>;
+ #io-trigger-cells = <1>;
+ status = "disabled";
+ };
+
+ resistive_touch: resistive-touch {
+ compatible = "microchip,sama5d2-resistive-touch";
+ io-channels = <&adc 19>, <&adc 20>, <&adc 21>;
+ io-channel-names = "x", "y", "pressure";
+ io-triggers = <&adc 1>;
+ microchip,pressure-threshold = <10000>;
status = "disabled";
};
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v6 04/11] thermal: armada: Clarify control registers accesses
From: Gregory CLEMENT @ 2017-12-22 15:33 UTC (permalink / raw)
To: Miquel Raynal
Cc: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Antoine Tenart, Nadav Haklai, Baruch Siach,
David Sniatkiwicz
In-Reply-To: <20171222093226.23456-5-miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Hi Miquel,
On ven., déc. 22 2017, Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Bindings were incomplete for a long time by only exposing one of the two
> available control registers. To ease the migration to the full bindings
> (already in use for the Armada 375 SoC), rename the pointers for
> clarification. This way, it will only be needed to add another pointer
> to access the other control register when the time comes.
>
> This avoids dangerous situations where the offset 0 of the control
> area can be either one register or the other depending on the bindings
> used. After this change, device trees of other SoCs could be migrated to
> the "full" bindings if they may benefit from features from the
> unaccessible register, without any change in the driver.
>
> Signed-off-by: Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> Reviewed-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
I tested that there was no regression on an Armada XP based board:
PlatHome OpenBlocks AX3-4, and on an Armada 388 one: SolidRun Clearfog
A1. For both of them it was OK:
Tested-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Gregory
> ---
> drivers/thermal/armada_thermal.c | 76 ++++++++++++++++++++++++++++------------
> 1 file changed, 54 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
> index f350d7efd35a..d58376eba6d9 100644
> --- a/drivers/thermal/armada_thermal.c
> +++ b/drivers/thermal/armada_thermal.c
> @@ -39,12 +39,21 @@
> #define A375_HW_RESETn BIT(8)
> #define A380_HW_RESET BIT(8)
>
> +/* Legacy bindings */
> +#define LEGACY_CONTROL_MEM_LEN 0x4
> +
> +/* Current bindings with the 2 control registers under the same memory area */
> +#define LEGACY_CONTROL1_OFFSET 0x0
> +#define CONTROL0_OFFSET 0x0
> +#define CONTROL1_OFFSET 0x4
> +
> struct armada_thermal_data;
>
> /* Marvell EBU Thermal Sensor Dev Structure */
> struct armada_thermal_priv {
> void __iomem *sensor;
> - void __iomem *control;
> + void __iomem *control0;
> + void __iomem *control1;
> struct armada_thermal_data *data;
> };
>
> @@ -66,27 +75,28 @@ struct armada_thermal_data {
> unsigned int temp_shift;
> unsigned int temp_mask;
> u32 is_valid_bit;
> + bool needs_control0;
> };
>
> static void armadaxp_init_sensor(struct platform_device *pdev,
> struct armada_thermal_priv *priv)
> {
> - unsigned long reg;
> + u32 reg;
>
> - reg = readl_relaxed(priv->control);
> + reg = readl_relaxed(priv->control1);
> reg |= PMU_TDC0_OTF_CAL_MASK;
> - writel(reg, priv->control);
> + writel(reg, priv->control1);
>
> /* Reference calibration value */
> reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
> reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
> - writel(reg, priv->control);
> + writel(reg, priv->control1);
>
> /* Reset the sensor */
> - reg = readl_relaxed(priv->control);
> - writel((reg | PMU_TDC0_SW_RST_MASK), priv->control);
> + reg = readl_relaxed(priv->control1);
> + writel((reg | PMU_TDC0_SW_RST_MASK), priv->control1);
>
> - writel(reg, priv->control);
> + writel(reg, priv->control1);
>
> /* Enable the sensor */
> reg = readl_relaxed(priv->sensor);
> @@ -97,19 +107,19 @@ static void armadaxp_init_sensor(struct platform_device *pdev,
> static void armada370_init_sensor(struct platform_device *pdev,
> struct armada_thermal_priv *priv)
> {
> - unsigned long reg;
> + u32 reg;
>
> - reg = readl_relaxed(priv->control);
> + reg = readl_relaxed(priv->control1);
> reg |= PMU_TDC0_OTF_CAL_MASK;
> - writel(reg, priv->control);
> + writel(reg, priv->control1);
>
> /* Reference calibration value */
> reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
> reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
> - writel(reg, priv->control);
> + writel(reg, priv->control1);
>
> reg &= ~PMU_TDC0_START_CAL_MASK;
> - writel(reg, priv->control);
> + writel(reg, priv->control1);
>
> msleep(10);
> }
> @@ -117,30 +127,30 @@ static void armada370_init_sensor(struct platform_device *pdev,
> static void armada375_init_sensor(struct platform_device *pdev,
> struct armada_thermal_priv *priv)
> {
> - unsigned long reg;
> + u32 reg;
>
> - reg = readl(priv->control + 4);
> + reg = readl(priv->control1);
> reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
> reg &= ~A375_READOUT_INVERT;
> reg &= ~A375_HW_RESETn;
>
> - writel(reg, priv->control + 4);
> + writel(reg, priv->control1);
> msleep(20);
>
> reg |= A375_HW_RESETn;
> - writel(reg, priv->control + 4);
> + writel(reg, priv->control1);
> msleep(50);
> }
>
> static void armada380_init_sensor(struct platform_device *pdev,
> struct armada_thermal_priv *priv)
> {
> - unsigned long reg = readl_relaxed(priv->control);
> + u32 reg = readl_relaxed(priv->control1);
>
> /* Reset hardware once */
> if (!(reg & A380_HW_RESET)) {
> reg |= A380_HW_RESET;
> - writel(reg, priv->control);
> + writel(reg, priv->control1);
> msleep(10);
> }
> }
> @@ -214,6 +224,7 @@ static const struct armada_thermal_data armada375_data = {
> .coef_b = 3171900000UL,
> .coef_m = 10000000UL,
> .coef_div = 13616,
> + .needs_control0 = true,
> };
>
> static const struct armada_thermal_data armada380_data = {
> @@ -253,6 +264,7 @@ MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
>
> static int armada_thermal_probe(struct platform_device *pdev)
> {
> + void __iomem *control = NULL;
> struct thermal_zone_device *thermal;
> const struct of_device_id *match;
> struct armada_thermal_priv *priv;
> @@ -272,11 +284,31 @@ static int armada_thermal_probe(struct platform_device *pdev)
> return PTR_ERR(priv->sensor);
>
> res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> - priv->control = devm_ioremap_resource(&pdev->dev, res);
> - if (IS_ERR(priv->control))
> - return PTR_ERR(priv->control);
> + control = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(control))
> + return PTR_ERR(control);
>
> priv->data = (struct armada_thermal_data *)match->data;
> +
> + /*
> + * Legacy DT bindings only described "control1" register (also referred
> + * as "control MSB" on old documentation). New bindings cover
> + * "control0/control LSB" and "control1/control MSB" registers within
> + * the same resource, which is then of size 8 instead of 4.
> + */
> + if (resource_size(res) == LEGACY_CONTROL_MEM_LEN) {
> + /* ->control0 unavailable in this configuration */
> + if (priv->data->needs_control0) {
> + dev_err(&pdev->dev, "No access to control0 register\n");
> + return -EINVAL;
> + }
> +
> + priv->control1 = control + LEGACY_CONTROL1_OFFSET;
> + } else {
> + priv->control0 = control + CONTROL0_OFFSET;
> + priv->control1 = control + CONTROL1_OFFSET;
> + }
> +
> priv->data->init_sensor(pdev, priv);
>
> thermal = thermal_zone_device_register("armada_thermal", 0, 0,
> --
> 2.11.0
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v6 11/11] thermal: armada: Give meaningful names to the thermal zones
From: Gregory CLEMENT @ 2017-12-22 15:36 UTC (permalink / raw)
To: Miquel Raynal
Cc: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland, linux-pm,
devicetree, linux-arm-kernel, Thomas Petazzoni, Antoine Tenart,
Nadav Haklai, Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222093226.23456-12-miquel.raynal@free-electrons.com>
Hi Miquel,
On ven., déc. 22 2017, Miquel Raynal <miquel.raynal@free-electrons.com> wrote:
> After registration to the thermal core, sysfs will make one entry
> per instance of the driver in /sys/class/thermal_zoneX and
> /sys/class/hwmon/hwmonX, X being the index of the instance, all of them
> having the type/name "armada_thermal".
>
> Until now there was only one thermal zone per SoC but SoCs like Armada
> A7K and Armada A8K have respectively two and three thermal zones (one
> per AP and one per CP) and this number is subject to grow in the future.
>
> Use dev_name() instead of the "armada_thermal" string to get a
> meaningful name and be able to identify the thermal zones from
> userspace.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
And here I also tested that when all the series was applied there was no
regression on an Armada XP based board: PlatHome OpenBlocks AX3-4, and
on an Armada 388 one: SolidRun Clearfog A1. hera again for both of them
it was OK:
Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Gregory
> ---
> drivers/thermal/armada_thermal.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
> index ea958e651312..454137f78eb3 100644
> --- a/drivers/thermal/armada_thermal.c
> +++ b/drivers/thermal/armada_thermal.c
> @@ -406,8 +406,8 @@ static int armada_thermal_probe(struct platform_device *pdev)
>
> priv->data->init_sensor(pdev, priv);
>
> - thermal = thermal_zone_device_register("armada_thermal", 0, 0,
> - priv, &ops, NULL, 0, 0);
> + thermal = thermal_zone_device_register(dev_name(&pdev->dev), 0, 0, priv,
> + &ops, NULL, 0, 0);
> if (IS_ERR(thermal)) {
> dev_err(&pdev->dev,
> "Failed to register thermal zone device\n");
> --
> 2.11.0
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH 1/5] bindings: regulator: added support for suspend states
From: Mark Brown @ 2017-12-22 15:49 UTC (permalink / raw)
To: Chunyan Zhang; +Cc: Rob Herring, devicetree, linux-kernel, Chunyan Zhang
In-Reply-To: <CAG2=9p9ahGgnz1Gos-o-o5PB9UH--2t3Lv54PaK5_f2jpNQnDQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1442 bytes --]
On Fri, Dec 22, 2017 at 02:05:21PM +0800, Chunyan Zhang wrote:
> On 22 December 2017 at 07:26, Rob Herring <robh@kernel.org> wrote:
> > On Thu, Dec 21, 2017 at 02:25:02PM +0800, Chunyan Zhang wrote:
> >> + - regulator-suspend-microvolt: the default voltage which regulator
> >> + should be set in suspend, this can be adjusted among
> >> + <regulator-suspend-min-microvolt, regulator-suspend-max-microvolt>
> > Perhaps this should stay a single property with: <target> <min> <max>
> Do you mean that change the property name from "regulator-suspend-microvolt" to
> "regulator-suspend-target-microvolt"?
> "regulator-suspend-microvolt" is the one that some SoC is using. My
> intention was just to keep that configuration still working.
Yeah, the regulator-suspend-microvolt is an existing property. Thinking
about it we should probably say that it's equivalent to setting both
-min and -max to the same value and possibly mark it as deprecated too.
It is documented in regulator.txt already.
> > Though why would you ever not try to set to the minimum voltage within
> > the range of <min> to <max>?
> IIUC, you mean just removing "regulator-suspend-microvolt", and use
> "regulator-suspend-min-microvolt" as the default value for suspend
> voltage?
> I think that can work, but would it be better to not remove that right
> now, since some one is using that?
Indeed. I think my suggestion above would cover things.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH 1/2] dt-binding: can: mcp2517fd: document device tree bindings
From: Patrick Menschel @ 2017-12-22 15:50 UTC (permalink / raw)
To: kernel-TqfNSX0MhmxHKSADF0wUEw
Cc: linux-can-u79uwXL29TY76Z2rM5mHXA, devicetree
In-Reply-To: <4E2DB518-A148-46CE-8267-73D292991BD2-TqfNSX0MhmxHKSADF0wUEw@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1867 bytes --]
Hi Martin,
as I wrote earlier, I would save the GPIO_LIB part for a driver update
later on as to me there seems to be no daily use case.
I think SLEEP is the preferred solution.
If the device is in SLEEP after probing, the logical step would be to
disable GPIO functions and configure INT0/GPIO0/XSTBY to XSTBY thus the
transceiver is also sleeping.
Best practice usually comes from practical usage.
If there already is a reference design PCB with the mcp2517fd, it would
make sense to see what the designer did connect to the optional GPIO
pins and then guess what additional use cases could be of interest.
Without that knowledge, you're prone to do over-engineering.
Regards,
Patrick
Am 17.12.2017 um 15:34 schrieb kernel-TqfNSX0MhmxHKSADF0wUEw@public.gmane.org:
> Hi Patrick!
>
> So I started implementing the GPIO_LIB implementation but
> I have hit an issue where I would like to get some feedback.
>
> So in principle the gpiolib works, but only if the device is
> not asleep and the clock is enabled, which at this very moment means
> that the can interface has to be up and running.
>
> So at this very moment the only option that I see would be to
> disable the sleep mode which the device enters after probing until
> the can-network interface is enabled (which enables the clock and
> start the oscillator) - with SLEEP enabled when GPIOLIB support
> is disabled.
>
> This is obviously not optimal from the power perspective…
>
> The other option would be starting the clock and oscillator
> as soon as a set_direction* (or reques/free) function is called.
> (where I would need to start using locks to avoid race conditions
> as well as clock usage counters...).
>
> Which of the above is the preferred solution? Are there other ideas
> how I could solve this dilemma?
>
>
> Martin
>
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 3992 bytes --]
^ permalink raw reply
* Re: [PATCH v6 11/11] thermal: armada: Give meaningful names to the thermal zones
From: Miquel RAYNAL @ 2017-12-22 15:51 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Antoine Tenart, Nadav Haklai, Baruch Siach,
David Sniatkiwicz
In-Reply-To: <873742epwb.fsf-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Hello Gregory,
On Fri, 22 Dec 2017 16:36:04 +0100
Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Hi Miquel,
>
> On ven., déc. 22 2017, Miquel Raynal
> <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
>
> > After registration to the thermal core, sysfs will make one entry
> > per instance of the driver in /sys/class/thermal_zoneX and
> > /sys/class/hwmon/hwmonX, X being the index of the instance, all of
> > them having the type/name "armada_thermal".
> >
> > Until now there was only one thermal zone per SoC but SoCs like
> > Armada A7K and Armada A8K have respectively two and three thermal
> > zones (one per AP and one per CP) and this number is subject to
> > grow in the future.
> >
> > Use dev_name() instead of the "armada_thermal" string to get a
> > meaningful name and be able to identify the thermal zones from
> > userspace.
> >
> > Signed-off-by: Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > Reviewed-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>
> And here I also tested that when all the series was applied there was
> no regression on an Armada XP based board: PlatHome OpenBlocks AX3-4,
> and on an Armada 388 one: SolidRun Clearfog A1. hera again for both
> of them it was OK:
Thank you for testing, on my side I checked the last version (minor
changes) with both an Armada-385-AP and an Armada-8040-DB.
I will resend the series very soon.
Thanks,
Miquèl
>
> Tested-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>
> Gregory
>
> > ---
> > drivers/thermal/armada_thermal.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/thermal/armada_thermal.c
> > b/drivers/thermal/armada_thermal.c index ea958e651312..454137f78eb3
> > 100644 --- a/drivers/thermal/armada_thermal.c
> > +++ b/drivers/thermal/armada_thermal.c
> > @@ -406,8 +406,8 @@ static int armada_thermal_probe(struct
> > platform_device *pdev)
> > priv->data->init_sensor(pdev, priv);
> >
> > - thermal = thermal_zone_device_register("armada_thermal",
> > 0, 0,
> > - priv, &ops, NULL,
> > 0, 0);
> > + thermal =
> > thermal_zone_device_register(dev_name(&pdev->dev), 0, 0, priv,
> > + &ops, NULL, 0, 0);
> > if (IS_ERR(thermal)) {
> > dev_err(&pdev->dev,
> > "Failed to register thermal zone
> > device\n"); --
> > 2.11.0
> >
>
--
Miquel Raynal, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 14/14] ARM: dts: at91: sama5d2: Add resistive touch device
From: Alexandre Belloni @ 2017-12-22 16:10 UTC (permalink / raw)
To: Eugen Hristev
Cc: nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, jic23-DgEjT+Ai2ygdnm+yROfE0A,
linux-input-u79uwXL29TY76Z2rM5mHXA,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1513955241-10985-15-git-send-email-eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Hi,
On 22/12/2017 at 17:07:21 +0200, Eugen Hristev wrote:
> Add the resistive touchscreen device, and the cell numbers to the
> ADC device.
>
> Signed-off-by: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> ---
> arch/arm/boot/dts/sama5d2.dtsi | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
> index b1a26b4..30b3797 100644
> --- a/arch/arm/boot/dts/sama5d2.dtsi
> +++ b/arch/arm/boot/dts/sama5d2.dtsi
> @@ -402,7 +402,6 @@
> compatible = "atmel,hlcdc-display-controller";
> #address-cells = <1>;
> #size-cells = <0>;
> -
This is an unrelated change.
> port@0 {
> #address-cells = <1>;
> #size-cells = <0>;
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v7 00/11] Armada thermal: improvements and A7K/A8K SoCs support
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Gregory Clement, Antoine Tenart, Nadav Haklai,
Miquel Raynal, Baruch Siach, David Sniatkiwicz
Hi,
This series takes over Baruch's series by integrating his patches about
supporting thermal on Armada 7K and 8K SoCs within a larger series with
several improvements on the armada_thermal.c driver.
For now, Armada 380 and CP110 compatibles share the same initialization
routine but this will probably change in the near future when adding
support for overheat interrupts.
DT bindings documentation is updated to match existing code.
Armada AP806 and CP110 DT are also updated with thermal nodes and have
already been accepted (thus absent in this series).
Thank you,
Miquèl
Changes since v6:
- Added Gregory's Tested-by tags.
- Added Rob's Reviewed-by tag on the bindings.
- Addressed Baruch's comment on the temperature derivation.
Baruch Siach (4):
dt-bindings: thermal: Describe Armada AP806 and CP110
thermal: armada: Use msleep for long delays
thermal: armada: Add support for Armada AP806
thermal: armada: Add support for Armada CP110
Miquel Raynal (7):
thermal: armada: Simplify the check of the validity bit
thermal: armada: Clarify control registers accesses
thermal: armada: Use real status register name
thermal: armada: Update Kconfig and module description
thermal: armada: Change sensors trim default value
thermal: armada: Wait sensors validity before exiting the init
callback
thermal: armada: Give meaningful names to the thermal zones
.../devicetree/bindings/thermal/armada-thermal.txt | 37 ++-
drivers/thermal/Kconfig | 4 +-
drivers/thermal/armada_thermal.c | 253 +++++++++++++++------
3 files changed, 214 insertions(+), 80 deletions(-)
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v7 01/11] dt-bindings: thermal: Describe Armada AP806 and CP110
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Gregory Clement, Antoine Tenart, Nadav Haklai,
Miquel Raynal, Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
From: Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
Add compatible strings for AP806 and CP110 that are part of the Armada
8k/7k line of SoCs.
Add a note on the differences in the size of the control area in
different bindings. This is an existing difference between the Armada
375 binding and the other boards already supported. The new AP806 and
CP110 bindings are similar to the existing Armada 375 in this regard.
Signed-off-by: Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
[<miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>: reword, additional details]
Signed-off-by: Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
.../devicetree/bindings/thermal/armada-thermal.txt | 37 +++++++++++++++-------
1 file changed, 25 insertions(+), 12 deletions(-)
diff --git a/Documentation/devicetree/bindings/thermal/armada-thermal.txt b/Documentation/devicetree/bindings/thermal/armada-thermal.txt
index 24aacf8948c5..e0d013a2e66d 100644
--- a/Documentation/devicetree/bindings/thermal/armada-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/armada-thermal.txt
@@ -2,22 +2,35 @@
Required properties:
-- compatible: Should be set to one of the following:
- marvell,armada370-thermal
- marvell,armada375-thermal
- marvell,armada380-thermal
- marvell,armadaxp-thermal
+- compatible: Should be set to one of the following:
+ * marvell,armada370-thermal
+ * marvell,armada375-thermal
+ * marvell,armada380-thermal
+ * marvell,armadaxp-thermal
+ * marvell,armada-ap806-thermal
+ * marvell,armada-cp110-thermal
-- reg: Device's register space.
- Two entries are expected, see the examples below.
- The first one is required for the sensor register;
- the second one is required for the control register
- to be used for sensor initialization (a.k.a. calibration).
+- reg: Device's register space.
+ Two entries are expected, see the examples below. The first one points
+ to the status register (4B). The second one points to the control
+ registers (8B).
+ Note: The compatibles marvell,armada370-thermal,
+ marvell,armada380-thermal, and marvell,armadaxp-thermal must point to
+ "control MSB/control 1", with size of 4 (deprecated binding), or point
+ to "control LSB/control 0" with size of 8 (current binding). All other
+ compatibles must point to "control LSB/control 0" with size of 8.
-Example:
+Examples:
+ /* Legacy bindings */
thermal@d0018300 {
compatible = "marvell,armada370-thermal";
- reg = <0xd0018300 0x4
+ reg = <0xd0018300 0x4
0xd0018304 0x4>;
};
+
+ ap_thermal: thermal@6f8084 {
+ compatible = "marvell,armada-ap806-thermal";
+ reg = <0x6f808C 0x4>,
+ <0x6f8084 0x8>;
+ };
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v7 02/11] thermal: armada: Use msleep for long delays
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm, devicetree, linux-arm-kernel, Thomas Petazzoni,
Gregory Clement, Antoine Tenart, Nadav Haklai, Miquel Raynal,
Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal@free-electrons.com>
From: Baruch Siach <baruch@tkos.co.il>
Use msleep for long (> 10ms) delays, instead of the busy waiting mdelay.
All delays are called from the probe routine, where scheduling is
allowed.
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/thermal/armada_thermal.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index 706d74798cbe..6c4af2622d4f 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -113,7 +113,7 @@ static void armada370_init_sensor(struct platform_device *pdev,
reg &= ~PMU_TDC0_START_CAL_MASK;
writel(reg, priv->control);
- mdelay(10);
+ msleep(10);
}
static void armada375_init_sensor(struct platform_device *pdev,
@@ -127,11 +127,11 @@ static void armada375_init_sensor(struct platform_device *pdev,
reg &= ~A375_HW_RESETn;
writel(reg, priv->control + 4);
- mdelay(20);
+ msleep(20);
reg |= A375_HW_RESETn;
writel(reg, priv->control + 4);
- mdelay(50);
+ msleep(50);
}
static void armada380_init_sensor(struct platform_device *pdev,
@@ -143,7 +143,7 @@ static void armada380_init_sensor(struct platform_device *pdev,
if (!(reg & A380_HW_RESET)) {
reg |= A380_HW_RESET;
writel(reg, priv->control);
- mdelay(10);
+ msleep(10);
}
}
--
2.11.0
^ permalink raw reply related
* [PATCH v7 03/11] thermal: armada: Simplify the check of the validity bit
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm, devicetree, linux-arm-kernel, Thomas Petazzoni,
Gregory Clement, Antoine Tenart, Nadav Haklai, Miquel Raynal,
Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal@free-electrons.com>
All Armada SoCs use one bit to declare if the sensor values are valid.
This bit moves across the versions of the IP.
The method until then was to do both a shift and compare with an useless
flag of "0x1". It is clearer and quicker to directly save the value that
must be ANDed instead of the bit position and do a single bitwise AND
operation.
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/thermal/armada_thermal.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index 6c4af2622d4f..f350d7efd35a 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -24,8 +24,6 @@
#include <linux/of_device.h>
#include <linux/thermal.h>
-#define THERMAL_VALID_MASK 0x1
-
/* Thermal Manager Control and Status Register */
#define PMU_TDC0_SW_RST_MASK (0x1 << 1)
#define PMU_TM_DISABLE_OFFS 0
@@ -67,7 +65,7 @@ struct armada_thermal_data {
/* Register shift and mask to access the sensor temperature */
unsigned int temp_shift;
unsigned int temp_mask;
- unsigned int is_valid_shift;
+ u32 is_valid_bit;
};
static void armadaxp_init_sensor(struct platform_device *pdev,
@@ -149,9 +147,9 @@ static void armada380_init_sensor(struct platform_device *pdev,
static bool armada_is_valid(struct armada_thermal_priv *priv)
{
- unsigned long reg = readl_relaxed(priv->sensor);
+ u32 reg = readl_relaxed(priv->sensor);
- return (reg >> priv->data->is_valid_shift) & THERMAL_VALID_MASK;
+ return reg & priv->data->is_valid_bit;
}
static int armada_get_temp(struct thermal_zone_device *thermal,
@@ -199,7 +197,7 @@ static const struct armada_thermal_data armadaxp_data = {
static const struct armada_thermal_data armada370_data = {
.is_valid = armada_is_valid,
.init_sensor = armada370_init_sensor,
- .is_valid_shift = 9,
+ .is_valid_bit = BIT(9),
.temp_shift = 10,
.temp_mask = 0x1ff,
.coef_b = 3153000000UL,
@@ -210,7 +208,7 @@ static const struct armada_thermal_data armada370_data = {
static const struct armada_thermal_data armada375_data = {
.is_valid = armada_is_valid,
.init_sensor = armada375_init_sensor,
- .is_valid_shift = 10,
+ .is_valid_bit = BIT(10),
.temp_shift = 0,
.temp_mask = 0x1ff,
.coef_b = 3171900000UL,
@@ -221,7 +219,7 @@ static const struct armada_thermal_data armada375_data = {
static const struct armada_thermal_data armada380_data = {
.is_valid = armada_is_valid,
.init_sensor = armada380_init_sensor,
- .is_valid_shift = 10,
+ .is_valid_bit = BIT(10),
.temp_shift = 0,
.temp_mask = 0x3ff,
.coef_b = 1172499100UL,
--
2.11.0
^ permalink raw reply related
* [PATCH v7 04/11] thermal: armada: Clarify control registers accesses
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm, devicetree, linux-arm-kernel, Thomas Petazzoni,
Gregory Clement, Antoine Tenart, Nadav Haklai, Miquel Raynal,
Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal@free-electrons.com>
Bindings were incomplete for a long time by only exposing one of the two
available control registers. To ease the migration to the full bindings
(already in use for the Armada 375 SoC), rename the pointers for
clarification. This way, it will only be needed to add another pointer
to access the other control register when the time comes.
This avoids dangerous situations where the offset 0 of the control
area can be either one register or the other depending on the bindings
used. After this change, device trees of other SoCs could be migrated to
the "full" bindings if they may benefit from features from the
unaccessible register, without any change in the driver.
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/thermal/armada_thermal.c | 76 ++++++++++++++++++++++++++++------------
1 file changed, 54 insertions(+), 22 deletions(-)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index f350d7efd35a..d58376eba6d9 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -39,12 +39,21 @@
#define A375_HW_RESETn BIT(8)
#define A380_HW_RESET BIT(8)
+/* Legacy bindings */
+#define LEGACY_CONTROL_MEM_LEN 0x4
+
+/* Current bindings with the 2 control registers under the same memory area */
+#define LEGACY_CONTROL1_OFFSET 0x0
+#define CONTROL0_OFFSET 0x0
+#define CONTROL1_OFFSET 0x4
+
struct armada_thermal_data;
/* Marvell EBU Thermal Sensor Dev Structure */
struct armada_thermal_priv {
void __iomem *sensor;
- void __iomem *control;
+ void __iomem *control0;
+ void __iomem *control1;
struct armada_thermal_data *data;
};
@@ -66,27 +75,28 @@ struct armada_thermal_data {
unsigned int temp_shift;
unsigned int temp_mask;
u32 is_valid_bit;
+ bool needs_control0;
};
static void armadaxp_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
- unsigned long reg;
+ u32 reg;
- reg = readl_relaxed(priv->control);
+ reg = readl_relaxed(priv->control1);
reg |= PMU_TDC0_OTF_CAL_MASK;
- writel(reg, priv->control);
+ writel(reg, priv->control1);
/* Reference calibration value */
reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
- writel(reg, priv->control);
+ writel(reg, priv->control1);
/* Reset the sensor */
- reg = readl_relaxed(priv->control);
- writel((reg | PMU_TDC0_SW_RST_MASK), priv->control);
+ reg = readl_relaxed(priv->control1);
+ writel((reg | PMU_TDC0_SW_RST_MASK), priv->control1);
- writel(reg, priv->control);
+ writel(reg, priv->control1);
/* Enable the sensor */
reg = readl_relaxed(priv->sensor);
@@ -97,19 +107,19 @@ static void armadaxp_init_sensor(struct platform_device *pdev,
static void armada370_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
- unsigned long reg;
+ u32 reg;
- reg = readl_relaxed(priv->control);
+ reg = readl_relaxed(priv->control1);
reg |= PMU_TDC0_OTF_CAL_MASK;
- writel(reg, priv->control);
+ writel(reg, priv->control1);
/* Reference calibration value */
reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
- writel(reg, priv->control);
+ writel(reg, priv->control1);
reg &= ~PMU_TDC0_START_CAL_MASK;
- writel(reg, priv->control);
+ writel(reg, priv->control1);
msleep(10);
}
@@ -117,30 +127,30 @@ static void armada370_init_sensor(struct platform_device *pdev,
static void armada375_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
- unsigned long reg;
+ u32 reg;
- reg = readl(priv->control + 4);
+ reg = readl(priv->control1);
reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
reg &= ~A375_READOUT_INVERT;
reg &= ~A375_HW_RESETn;
- writel(reg, priv->control + 4);
+ writel(reg, priv->control1);
msleep(20);
reg |= A375_HW_RESETn;
- writel(reg, priv->control + 4);
+ writel(reg, priv->control1);
msleep(50);
}
static void armada380_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
- unsigned long reg = readl_relaxed(priv->control);
+ u32 reg = readl_relaxed(priv->control1);
/* Reset hardware once */
if (!(reg & A380_HW_RESET)) {
reg |= A380_HW_RESET;
- writel(reg, priv->control);
+ writel(reg, priv->control1);
msleep(10);
}
}
@@ -214,6 +224,7 @@ static const struct armada_thermal_data armada375_data = {
.coef_b = 3171900000UL,
.coef_m = 10000000UL,
.coef_div = 13616,
+ .needs_control0 = true,
};
static const struct armada_thermal_data armada380_data = {
@@ -253,6 +264,7 @@ MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
static int armada_thermal_probe(struct platform_device *pdev)
{
+ void __iomem *control = NULL;
struct thermal_zone_device *thermal;
const struct of_device_id *match;
struct armada_thermal_priv *priv;
@@ -272,11 +284,31 @@ static int armada_thermal_probe(struct platform_device *pdev)
return PTR_ERR(priv->sensor);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- priv->control = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(priv->control))
- return PTR_ERR(priv->control);
+ control = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control))
+ return PTR_ERR(control);
priv->data = (struct armada_thermal_data *)match->data;
+
+ /*
+ * Legacy DT bindings only described "control1" register (also referred
+ * as "control MSB" on old documentation). New bindings cover
+ * "control0/control LSB" and "control1/control MSB" registers within
+ * the same resource, which is then of size 8 instead of 4.
+ */
+ if (resource_size(res) == LEGACY_CONTROL_MEM_LEN) {
+ /* ->control0 unavailable in this configuration */
+ if (priv->data->needs_control0) {
+ dev_err(&pdev->dev, "No access to control0 register\n");
+ return -EINVAL;
+ }
+
+ priv->control1 = control + LEGACY_CONTROL1_OFFSET;
+ } else {
+ priv->control0 = control + CONTROL0_OFFSET;
+ priv->control1 = control + CONTROL1_OFFSET;
+ }
+
priv->data->init_sensor(pdev, priv);
thermal = thermal_zone_device_register("armada_thermal", 0, 0,
--
2.11.0
^ permalink raw reply related
* [PATCH v7 05/11] thermal: armada: Use real status register name
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm, devicetree, linux-arm-kernel, Thomas Petazzoni,
Gregory Clement, Antoine Tenart, Nadav Haklai, Miquel Raynal,
Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal@free-electrons.com>
Three 32-bit registers are used to drive the thermal IP: control0,
control1 and status. The two control registers share the same name both
in the documentation and in the code, while the latter is referred as
"sensor" in the code. Rename this pointer to be called "status" in order
to be aligned with the documentation.
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/thermal/armada_thermal.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index d58376eba6d9..ceebabf45c53 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -51,7 +51,7 @@ struct armada_thermal_data;
/* Marvell EBU Thermal Sensor Dev Structure */
struct armada_thermal_priv {
- void __iomem *sensor;
+ void __iomem *status;
void __iomem *control0;
void __iomem *control1;
struct armada_thermal_data *data;
@@ -99,9 +99,9 @@ static void armadaxp_init_sensor(struct platform_device *pdev,
writel(reg, priv->control1);
/* Enable the sensor */
- reg = readl_relaxed(priv->sensor);
+ reg = readl_relaxed(priv->status);
reg &= ~PMU_TM_DISABLE_MASK;
- writel(reg, priv->sensor);
+ writel(reg, priv->status);
}
static void armada370_init_sensor(struct platform_device *pdev,
@@ -157,7 +157,7 @@ static void armada380_init_sensor(struct platform_device *pdev,
static bool armada_is_valid(struct armada_thermal_priv *priv)
{
- u32 reg = readl_relaxed(priv->sensor);
+ u32 reg = readl_relaxed(priv->status);
return reg & priv->data->is_valid_bit;
}
@@ -176,7 +176,7 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
return -EIO;
}
- reg = readl_relaxed(priv->sensor);
+ reg = readl_relaxed(priv->status);
reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask;
/* Get formula coeficients */
@@ -279,9 +279,9 @@ static int armada_thermal_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->sensor = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(priv->sensor))
- return PTR_ERR(priv->sensor);
+ priv->status = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->status))
+ return PTR_ERR(priv->status);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
control = devm_ioremap_resource(&pdev->dev, res);
--
2.11.0
^ permalink raw reply related
* [PATCH v7 06/11] thermal: armada: Add support for Armada AP806
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Gregory Clement, Antoine Tenart, Nadav Haklai,
Miquel Raynal, Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
From: Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
The AP806 component is integrated in the Armada 8K and 7K lines of
processors.
The thermal sensor sample field on the status register is a signed
value. Extend armada_get_temp() and the driver structure to handle
signed values.
Signed-off-by: Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
[<miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>: Changes when applying over the
previous patches, including the register names changes, also switched
the coefficients values to s64 instead of unsigned long to deal with
negative values and used do_div instead of the traditionnal '/']
Signed-off-by: Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Tested-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/thermal/armada_thermal.c | 74 +++++++++++++++++++++++++++++++---------
1 file changed, 58 insertions(+), 16 deletions(-)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index ceebabf45c53..f35289b1cea9 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -47,6 +47,11 @@
#define CONTROL0_OFFSET 0x0
#define CONTROL1_OFFSET 0x4
+/* TSEN refers to the temperature sensors within the AP */
+#define CONTROL0_TSEN_START BIT(0)
+#define CONTROL0_TSEN_RESET BIT(1)
+#define CONTROL0_TSEN_ENABLE BIT(2)
+
struct armada_thermal_data;
/* Marvell EBU Thermal Sensor Dev Structure */
@@ -66,10 +71,11 @@ struct armada_thermal_data {
bool (*is_valid)(struct armada_thermal_priv *);
/* Formula coeficients: temp = (b - m * reg) / div */
- unsigned long coef_b;
- unsigned long coef_m;
- unsigned long coef_div;
+ s64 coef_b;
+ s64 coef_m;
+ u32 coef_div;
bool inverted;
+ bool signed_sample;
/* Register shift and mask to access the sensor temperature */
unsigned int temp_shift;
@@ -155,6 +161,18 @@ static void armada380_init_sensor(struct platform_device *pdev,
}
}
+static void armada_ap806_init_sensor(struct platform_device *pdev,
+ struct armada_thermal_priv *priv)
+{
+ u32 reg;
+
+ reg = readl_relaxed(priv->control0);
+ reg &= ~CONTROL0_TSEN_RESET;
+ reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE;
+ writel(reg, priv->control0);
+ msleep(10);
+}
+
static bool armada_is_valid(struct armada_thermal_priv *priv)
{
u32 reg = readl_relaxed(priv->status);
@@ -163,11 +181,11 @@ static bool armada_is_valid(struct armada_thermal_priv *priv)
}
static int armada_get_temp(struct thermal_zone_device *thermal,
- int *temp)
+ int *temp)
{
struct armada_thermal_priv *priv = thermal->devdata;
- unsigned long reg;
- unsigned long m, b, div;
+ u32 reg, div;
+ s64 sample, b, m;
/* Valid check */
if (priv->data->is_valid && !priv->data->is_valid(priv)) {
@@ -178,6 +196,11 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
reg = readl_relaxed(priv->status);
reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask;
+ if (priv->data->signed_sample)
+ /* The most significant bit is the sign bit */
+ sample = sign_extend32(reg, fls(priv->data->temp_mask) - 1);
+ else
+ sample = reg;
/* Get formula coeficients */
b = priv->data->coef_b;
@@ -185,9 +208,10 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
div = priv->data->coef_div;
if (priv->data->inverted)
- *temp = ((m * reg) - b) / div;
+ *temp = div_s64((m * sample) - b, div);
else
- *temp = (b - (m * reg)) / div;
+ *temp = div_s64(b - (m * sample), div);
+
return 0;
}
@@ -199,8 +223,8 @@ static const struct armada_thermal_data armadaxp_data = {
.init_sensor = armadaxp_init_sensor,
.temp_shift = 10,
.temp_mask = 0x1ff,
- .coef_b = 3153000000UL,
- .coef_m = 10000000UL,
+ .coef_b = 3153000000ULL,
+ .coef_m = 10000000ULL,
.coef_div = 13825,
};
@@ -210,8 +234,8 @@ static const struct armada_thermal_data armada370_data = {
.is_valid_bit = BIT(9),
.temp_shift = 10,
.temp_mask = 0x1ff,
- .coef_b = 3153000000UL,
- .coef_m = 10000000UL,
+ .coef_b = 3153000000ULL,
+ .coef_m = 10000000ULL,
.coef_div = 13825,
};
@@ -221,8 +245,8 @@ static const struct armada_thermal_data armada375_data = {
.is_valid_bit = BIT(10),
.temp_shift = 0,
.temp_mask = 0x1ff,
- .coef_b = 3171900000UL,
- .coef_m = 10000000UL,
+ .coef_b = 3171900000ULL,
+ .coef_m = 10000000ULL,
.coef_div = 13616,
.needs_control0 = true,
};
@@ -233,12 +257,26 @@ static const struct armada_thermal_data armada380_data = {
.is_valid_bit = BIT(10),
.temp_shift = 0,
.temp_mask = 0x3ff,
- .coef_b = 1172499100UL,
- .coef_m = 2000096UL,
+ .coef_b = 1172499100ULL,
+ .coef_m = 2000096ULL,
.coef_div = 4201,
.inverted = true,
};
+static const struct armada_thermal_data armada_ap806_data = {
+ .is_valid = armada_is_valid,
+ .init_sensor = armada_ap806_init_sensor,
+ .is_valid_bit = BIT(16),
+ .temp_shift = 0,
+ .temp_mask = 0x3ff,
+ .coef_b = -150000LL,
+ .coef_m = 423ULL,
+ .coef_div = 1,
+ .inverted = true,
+ .signed_sample = true,
+ .needs_control0 = true,
+};
+
static const struct of_device_id armada_thermal_id_table[] = {
{
.compatible = "marvell,armadaxp-thermal",
@@ -257,6 +295,10 @@ static const struct of_device_id armada_thermal_id_table[] = {
.data = &armada380_data,
},
{
+ .compatible = "marvell,armada-ap806-thermal",
+ .data = &armada_ap806_data,
+ },
+ {
/* sentinel */
},
};
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v7 07/11] thermal: armada: Add support for Armada CP110
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm, devicetree, linux-arm-kernel, Thomas Petazzoni,
Gregory Clement, Antoine Tenart, Nadav Haklai, Miquel Raynal,
Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal@free-electrons.com>
From: Baruch Siach <baruch@tkos.co.il>
The CP110 component is integrated in the Armada 8k and 7k lines of
processors.
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
[<miquel.raynal@free-electrons.com>: renamed the register pointers as
well as some definitions related to the new register names and
simplified the init sequence for Armada 380]
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/thermal/armada_thermal.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index f35289b1cea9..f2eba2a6f1a5 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -37,7 +37,6 @@
#define A375_UNIT_CONTROL_MASK 0x7
#define A375_READOUT_INVERT BIT(15)
#define A375_HW_RESETn BIT(8)
-#define A380_HW_RESET BIT(8)
/* Legacy bindings */
#define LEGACY_CONTROL_MEM_LEN 0x4
@@ -52,6 +51,10 @@
#define CONTROL0_TSEN_RESET BIT(1)
#define CONTROL0_TSEN_ENABLE BIT(2)
+/* EXT_TSEN refers to the external temperature sensors, out of the AP */
+#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
+#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
+
struct armada_thermal_data;
/* Marvell EBU Thermal Sensor Dev Structure */
@@ -153,12 +156,11 @@ static void armada380_init_sensor(struct platform_device *pdev,
{
u32 reg = readl_relaxed(priv->control1);
- /* Reset hardware once */
- if (!(reg & A380_HW_RESET)) {
- reg |= A380_HW_RESET;
- writel(reg, priv->control1);
- msleep(10);
- }
+ /* Disable the HW/SW reset */
+ reg |= CONTROL1_EXT_TSEN_HW_RESETn;
+ reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
+ writel(reg, priv->control1);
+ msleep(10);
}
static void armada_ap806_init_sensor(struct platform_device *pdev,
@@ -277,6 +279,19 @@ static const struct armada_thermal_data armada_ap806_data = {
.needs_control0 = true,
};
+static const struct armada_thermal_data armada_cp110_data = {
+ .is_valid = armada_is_valid,
+ .init_sensor = armada380_init_sensor,
+ .is_valid_bit = BIT(10),
+ .temp_shift = 0,
+ .temp_mask = 0x3ff,
+ .coef_b = 1172499100ULL,
+ .coef_m = 2000096ULL,
+ .coef_div = 4201,
+ .inverted = true,
+ .needs_control0 = true,
+};
+
static const struct of_device_id armada_thermal_id_table[] = {
{
.compatible = "marvell,armadaxp-thermal",
@@ -299,6 +314,10 @@ static const struct of_device_id armada_thermal_id_table[] = {
.data = &armada_ap806_data,
},
{
+ .compatible = "marvell,armada-cp110-thermal",
+ .data = &armada_cp110_data,
+ },
+ {
/* sentinel */
},
};
--
2.11.0
^ permalink raw reply related
* [PATCH v7 08/11] thermal: armada: Update Kconfig and module description
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm, devicetree, linux-arm-kernel, Thomas Petazzoni,
Gregory Clement, Antoine Tenart, Nadav Haklai, Miquel Raynal,
Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal@free-electrons.com>
Update Armada thermal driver Kconfig entry as well as the driver's
MODULE_DESCRIPTION content, now that 64-bit SoCs are also supported,
eg. Armada 7K and Armada 8K.
Use the generic term "Marvell EBU Armada SoCs" instead of listing all
the supported SoCs everywhere (excepted in the Kconfig description,
where it is useful to have a list).
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/thermal/Kconfig | 4 ++--
drivers/thermal/armada_thermal.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 315ae2926e20..b6adc54b96f1 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -301,13 +301,13 @@ config DB8500_THERMAL
thermal zone if trip points reached.
config ARMADA_THERMAL
- tristate "Armada 370/XP thermal management"
+ tristate "Marvell EBU Armada SoCs thermal management"
depends on ARCH_MVEBU || COMPILE_TEST
depends on HAS_IOMEM
depends on OF
help
Enable this option if you want to have support for thermal management
- controller present in Armada 370 and Armada XP SoC.
+ controller present in Marvell EBU Armada SoCs (370,375,XP,38x,7K,8K).
config DA9062_THERMAL
tristate "DA9062/DA9061 Dialog Semiconductor thermal driver"
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index f2eba2a6f1a5..d426b230e1c5 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -1,5 +1,5 @@
/*
- * Marvell Armada 370/XP thermal sensor driver
+ * Marvell EBU Armada SoCs thermal sensor driver
*
* Copyright (C) 2013 Marvell
*
@@ -407,5 +407,5 @@ static struct platform_driver armada_thermal_driver = {
module_platform_driver(armada_thermal_driver);
MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
-MODULE_DESCRIPTION("Armada 370/XP thermal driver");
+MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver");
MODULE_LICENSE("GPL v2");
--
2.11.0
^ permalink raw reply related
* [PATCH v7 09/11] thermal: armada: Change sensors trim default value
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Gregory Clement, Antoine Tenart, Nadav Haklai,
Miquel Raynal, Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Errata #132698 highlights an error in the default value of Tc trim.
Set this parameter to b'011.
Suggested-by: David Sniatkiwicz <davidsn-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/thermal/armada_thermal.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index d426b230e1c5..e6025d215cb5 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -46,6 +46,10 @@
#define CONTROL0_OFFSET 0x0
#define CONTROL1_OFFSET 0x4
+/* Errata fields */
+#define CONTROL0_TSEN_TC_TRIM_MASK 0x7
+#define CONTROL0_TSEN_TC_TRIM_VAL 0x3
+
/* TSEN refers to the temperature sensors within the AP */
#define CONTROL0_TSEN_START BIT(0)
#define CONTROL0_TSEN_RESET BIT(1)
@@ -161,6 +165,15 @@ static void armada380_init_sensor(struct platform_device *pdev,
reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
writel(reg, priv->control1);
msleep(10);
+
+ /* Set Tsen Tc Trim to correct default value (errata #132698) */
+ if (priv->control0) {
+ reg = readl_relaxed(priv->control0);
+ reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
+ reg |= CONTROL0_TSEN_TC_TRIM_VAL;
+ writel(reg, priv->control0);
+ msleep(10);
+ }
}
static void armada_ap806_init_sensor(struct platform_device *pdev,
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v7 10/11] thermal: armada: Wait sensors validity before exiting the init callback
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Gregory Clement, Antoine Tenart, Nadav Haklai,
Miquel Raynal, Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The thermal core will check for sensors validity right after the
initialization callback has returned. As the initialization routine make
a reset, the sensors are not ready immediately and the core spawns an
error in the dmesg. Avoid this annoying situation by polling on the
validity bit before exiting from these routines. This also avoid the use
of blind sleeps.
Suggested-by: David Sniatkiwicz <davidsn-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/thermal/armada_thermal.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index e6025d215cb5..a4befd2d683d 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -23,6 +23,7 @@
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/thermal.h>
+#include <linux/iopoll.h>
/* Thermal Manager Control and Status Register */
#define PMU_TDC0_SW_RST_MASK (0x1 << 1)
@@ -59,6 +60,9 @@
#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
+#define STATUS_POLL_PERIOD_US 1000
+#define STATUS_POLL_TIMEOUT_US 100000
+
struct armada_thermal_data;
/* Marvell EBU Thermal Sensor Dev Structure */
@@ -155,6 +159,16 @@ static void armada375_init_sensor(struct platform_device *pdev,
msleep(50);
}
+static void armada_wait_sensor_validity(struct armada_thermal_priv *priv)
+{
+ u32 reg;
+
+ readl_relaxed_poll_timeout(priv->status, reg,
+ reg & priv->data->is_valid_bit,
+ STATUS_POLL_PERIOD_US,
+ STATUS_POLL_TIMEOUT_US);
+}
+
static void armada380_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
@@ -164,7 +178,6 @@ static void armada380_init_sensor(struct platform_device *pdev,
reg |= CONTROL1_EXT_TSEN_HW_RESETn;
reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
writel(reg, priv->control1);
- msleep(10);
/* Set Tsen Tc Trim to correct default value (errata #132698) */
if (priv->control0) {
@@ -172,8 +185,10 @@ static void armada380_init_sensor(struct platform_device *pdev,
reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
reg |= CONTROL0_TSEN_TC_TRIM_VAL;
writel(reg, priv->control0);
- msleep(10);
}
+
+ /* Wait the sensors to be valid or the core will warn the user */
+ armada_wait_sensor_validity(priv);
}
static void armada_ap806_init_sensor(struct platform_device *pdev,
@@ -185,7 +200,9 @@ static void armada_ap806_init_sensor(struct platform_device *pdev,
reg &= ~CONTROL0_TSEN_RESET;
reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE;
writel(reg, priv->control0);
- msleep(10);
+
+ /* Wait the sensors to be valid or the core will warn the user */
+ armada_wait_sensor_validity(priv);
}
static bool armada_is_valid(struct armada_thermal_priv *priv)
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v7 11/11] thermal: armada: Give meaningful names to the thermal zones
From: Miquel Raynal @ 2017-12-22 16:14 UTC (permalink / raw)
To: Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland
Cc: linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Gregory Clement, Antoine Tenart, Nadav Haklai,
Miquel Raynal, Baruch Siach, David Sniatkiwicz
In-Reply-To: <20171222161413.20816-1-miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
After registration to the thermal core, sysfs will make one entry
per instance of the driver in /sys/class/thermal_zoneX and
/sys/class/hwmon/hwmonX, X being the index of the instance, all of them
having the type/name "armada_thermal".
Until now there was only one thermal zone per SoC but SoCs like Armada
A7K and Armada A8K have respectively two and three thermal zones (one
per AP and one per CP) and this number is subject to grow in the future.
Use dev_name() instead of the "armada_thermal" string to get a
meaningful name and be able to identify the thermal zones from
userspace.
Signed-off-by: Miquel Raynal <miquel.raynal-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Tested-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/thermal/armada_thermal.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index a4befd2d683d..4c275ec10ac5 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -402,8 +402,8 @@ static int armada_thermal_probe(struct platform_device *pdev)
priv->data->init_sensor(pdev, priv);
- thermal = thermal_zone_device_register("armada_thermal", 0, 0,
- priv, &ops, NULL, 0, 0);
+ thermal = thermal_zone_device_register(dev_name(&pdev->dev), 0, 0, priv,
+ &ops, NULL, 0, 0);
if (IS_ERR(thermal)) {
dev_err(&pdev->dev,
"Failed to register thermal zone device\n");
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCHv3 RESEND 1/3] Documentation: dt: memory: ti-emif: add edac support under emif
From: Tero Kristo @ 2017-12-22 16:23 UTC (permalink / raw)
To: devicetree; +Cc: Tony Lindgren, Rob Herring, linux-omap, linux-arm-kernel
Certain revisions of the TI EMIF IP contain ECC support in them. Reflect
this in the DT binding.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <robh+dt@kernel.org>
---
Just resending this patch, missed adding devicetree list on this previously
and it got lost.
.../devicetree/bindings/memory-controllers/ti/emif.txt | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
index 0db6047..f56a347 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
@@ -3,12 +3,16 @@
EMIF - External Memory Interface - is an SDRAM controller used in
TI SoCs. EMIF supports, based on the IP revision, one or more of
DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance
-of the EMIF IP and memory parts attached to it.
+of the EMIF IP and memory parts attached to it. Certain revisions
+of the EMIF IP controller also contain optional ECC support, which
+corrects one bit errors and detects two bit errors.
Required properties:
- compatible : Should be of the form "ti,emif-<ip-rev>" where <ip-rev>
is the IP revision of the specific EMIF instance.
For am437x should be ti,emif-am4372.
+ For dra7xx should be ti,emif-dra7xx.
+ For k2x family, should be ti,emif-keystone.
- phy-type : <u32> indicating the DDR phy type. Following are the
allowed values
@@ -42,6 +46,10 @@ Optional properties:
- hw-caps-temp-alert : Have this property if the controller
has capability for generating SDRAM temperature alerts
+- interrupts : A list of interrupt specifiers for memory
+ controller interrupts, if available. Required for EMIF instances
+ that support ECC.
+
Example:
emif1: emif@0x4c000000 {
@@ -54,3 +62,9 @@ emif1: emif@0x4c000000 {
hw-caps-ll-interface;
hw-caps-temp-alert;
};
+
+emif1: emif@4c000000 {
+ compatible = "ti,emif-dra7";
+ reg = <0x4c000000 0x200>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+};
--
1.9.1
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
^ permalink raw reply related
* Re: [PATCH 13/14] input: touchscreen: sama5d2_rts: SAMA5D2 Resistive touchscreen driver
From: Philippe Ombredanne @ 2017-12-22 16:29 UTC (permalink / raw)
To: Eugen Hristev
Cc: Nicolas Ferre, ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA,
Alexandre Belloni, linux-iio-u79uwXL29TY76Z2rM5mHXA,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, LKML,
Jonathan Cameron, linux-input-u79uwXL29TY76Z2rM5mHXA,
Dmitry Torokhov
In-Reply-To: <1513955241-10985-14-git-send-email-eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Eugen,
On Fri, Dec 22, 2017 at 4:07 PM, Eugen Hristev
<eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org> wrote:
> This is the implementation of the Microchip SAMA5D2 SOC resistive
> touchscreen driver.
<snip>
> --- /dev/null
> +++ b/drivers/input/touchscreen/sama5d2_rts.c
> @@ -0,0 +1,287 @@
> +/*
> + * Microchip resistive touchscreen (RTS) driver for SAMA5D2.
> + *
> + * Copyright (C) 2017 Microchip Technology,
> + * Author: Eugen Hristev <eugen.hristev-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
IMHO this should be this as a the first line instead as documented in
Thomas patch set [0] :
> +// SPDX-License-Identifier: GPL-2.0
I am just a lowly messenger and my weightless voice is as light as the
down feather of a new born goose. But if you have concerns with using
C++ comment styles as you should, please read Linus [1][2][3],
Thomas[4] and Greg[5] comments on the topic.
[0] https://lkml.org/lkml/2017/12/4/934
[1] https://lkml.org/lkml/2017/11/2/715
[2] https://lkml.org/lkml/2017/11/25/125
[3] https://lkml.org/lkml/2017/11/25/133
[4] https://lkml.org/lkml/2017/11/2/805
[5] https://lkml.org/lkml/2017/10/19/165
--
Cordially
Philippe Ombredanne, a kernel licensing scruffy
^ permalink raw reply
* Re: [PATCH v4] hwrng: exynos - add Samsung Exynos True RNG driver
From: Łukasz Stelmach @ 2017-12-22 16:38 UTC (permalink / raw)
To: Philippe Ombredanne
Cc: Andrew F . Davis, PrasannaKumar Muralidharan, Rob Herring,
Matt Mackall, Herbert Xu, Krzysztof Kozlowski, Kukjin Kim,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
linux-crypto, linux-samsung-soc, LKML, Marek Szyprowski,
Bartlomiej Zolnierkiewicz
In-Reply-To: <CAOFm3uG2aBHWUgVyzPuU8XJaLbm78cWEuWvgLEvNfc-hiefAbw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2533 bytes --]
It was <2017-12-22 pią 14:34>, when Philippe Ombredanne wrote:
> Łukasz,
>
> On Fri, Dec 22, 2017 at 2:23 PM, Łukasz Stelmach <l.stelmach@samsung.com> wrote:
>> Add support for True Random Number Generator found in Samsung Exynos
>> 5250+ SoCs.
>>
>> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
>> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
>
> <snip>
>
>> --- /dev/null
>> +++ b/drivers/char/hw_random/exynos-trng.c
>> @@ -0,0 +1,245 @@
>> +/*
>> + * RNG driver for Exynos TRNGs
>> + *
>> + * Author: Łukasz Stelmach <l.stelmach@samsung.com>
>> + *
>> + * Copyright 2017 (c) Samsung Electronics Software, Inc.
>> + *
>> + * Based on the Exynos PRNG driver drivers/crypto/exynos-rng by
>> + * Krzysztof Kozłowski <krzk@kernel.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;
>> + *
>> + * 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.
>> + */
>
>
> Would you mind using the new SPDX tags documented in Thomas patch set
> [1] rather than this fine but longer legalese?
>
> And if you could spread the word to others in your team this would be very nice.
> See also this fine article posted by Mauro on the Samsung Open Source
> Group Blog [2]
> Thank you!
Cool! We've been using SPDX to tag RPM packages in Tizen for three years or
more. ;-)
>> +MODULE_LICENSE("GPL");
>
> Per module.h this means GPL2 or later. This is not matching your
> license above which does not state any version and therefore would
> mean GPL1 or later,
Thanks for spotting. My intention is GPL-2.0.
> Please make sure you use something and common rather than this and
> make sure your MODULE_LICENSE is consistent with the top level
> license.
>
> Was it this way in the code from Krzysztof?
Yes. And omap-rng, the second of my sources of reference, too. Actually,
the majority of modules still specify "GPL".
281 | "Dual */*"
2082 | "GPL v2"
6359 | "GPL"
---- +---------
8784 | Total
Fixing.
> [1] https://lkml.org/lkml/2017/12/4/934
> [2] https://blogs.s-osg.org/linux-kernel-license-practices-revisited-spdx/
--
Łukasz Stelmach
Samsung R&D Institute Poland
Samsung Electronics
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 472 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox