From 2d53809594afaf2ae66a90a3142c1b702fd3bcea Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Mon, 6 Jul 2015 15:57:44 -0700 Subject: Input: zforce_ts - convert to use the gpiod interface Use the new GPIO descriptor interface to handle the zForce GPIOs. This simplifies the code and allows transparently handle GPIO polarity, as specified in device tree data. Also switch to using gpio_{set|get}_value_cansleep() since none of the callers is in atomic context and cansleep variant allows more GPIO controllers to be used with the touchscreen. Signed-off-by: Dirk Behme Signed-off-by: Dmitry Torokhov --- include/linux/platform_data/zforce_ts.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/zforce_ts.h b/include/linux/platform_data/zforce_ts.h index 0472ab2f6ede..7bdece8ef33e 100644 --- a/include/linux/platform_data/zforce_ts.h +++ b/include/linux/platform_data/zforce_ts.h @@ -16,9 +16,6 @@ #define _LINUX_INPUT_ZFORCE_TS_H struct zforce_ts_platdata { - int gpio_int; - int gpio_rst; - unsigned int x_max; unsigned int y_max; }; -- cgit v1.2.3 From 28a74c050060c17b1edaee2d60470a33be476941 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 6 Jul 2015 11:48:47 -0700 Subject: Input: pixcir_i2c_ts - move platform data Let's move driver's platform data definitions from include/linux/input/ into include/linux/platform_data/ so that it stays with the rest of platform data definitions. Acked-by: Roger Quadros Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 2 +- include/linux/input/pixcir_ts.h | 64 ----------------------------- include/linux/platform_data/pixcir_i2c_ts.h | 64 +++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 65 deletions(-) delete mode 100644 include/linux/input/pixcir_ts.h create mode 100644 include/linux/platform_data/pixcir_i2c_ts.h (limited to 'include/linux/platform_data') diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 2c2107147319..f7d90997a786 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -24,11 +24,11 @@ #include #include #include -#include #include #include #include #include +#include #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h deleted file mode 100644 index 7bae83b7c396..000000000000 --- a/include/linux/input/pixcir_ts.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _PIXCIR_I2C_TS_H -#define _PIXCIR_I2C_TS_H - -/* - * Register map - */ -#define PIXCIR_REG_POWER_MODE 51 -#define PIXCIR_REG_INT_MODE 52 - -/* - * Power modes: - * active: max scan speed - * idle: lower scan speed with automatic transition to active on touch - * halt: datasheet says sleep but this is more like halt as the chip - * clocks are cut and it can only be brought out of this mode - * using the RESET pin. - */ -enum pixcir_power_mode { - PIXCIR_POWER_ACTIVE, - PIXCIR_POWER_IDLE, - PIXCIR_POWER_HALT, -}; - -#define PIXCIR_POWER_MODE_MASK 0x03 -#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2) - -/* - * Interrupt modes: - * periodical: interrupt is asserted periodicaly - * diff coordinates: interrupt is asserted when coordinates change - * level on touch: interrupt level asserted during touch - * pulse on touch: interrupt pulse asserted druing touch - * - */ -enum pixcir_int_mode { - PIXCIR_INT_PERIODICAL, - PIXCIR_INT_DIFF_COORD, - PIXCIR_INT_LEVEL_TOUCH, - PIXCIR_INT_PULSE_TOUCH, -}; - -#define PIXCIR_INT_MODE_MASK 0x03 -#define PIXCIR_INT_ENABLE (1UL << 3) -#define PIXCIR_INT_POL_HIGH (1UL << 2) - -/** - * struct pixcir_irc_chip_data - chip related data - * @max_fingers: Max number of fingers reported simultaneously by h/w - * @has_hw_ids: Hardware supports finger tracking IDs - * - */ -struct pixcir_i2c_chip_data { - u8 max_fingers; - bool has_hw_ids; -}; - -struct pixcir_ts_platform_data { - int x_max; - int y_max; - int gpio_attb; /* GPIO connected to ATTB line */ - struct pixcir_i2c_chip_data chip; -}; - -#endif diff --git a/include/linux/platform_data/pixcir_i2c_ts.h b/include/linux/platform_data/pixcir_i2c_ts.h new file mode 100644 index 000000000000..7bae83b7c396 --- /dev/null +++ b/include/linux/platform_data/pixcir_i2c_ts.h @@ -0,0 +1,64 @@ +#ifndef _PIXCIR_I2C_TS_H +#define _PIXCIR_I2C_TS_H + +/* + * Register map + */ +#define PIXCIR_REG_POWER_MODE 51 +#define PIXCIR_REG_INT_MODE 52 + +/* + * Power modes: + * active: max scan speed + * idle: lower scan speed with automatic transition to active on touch + * halt: datasheet says sleep but this is more like halt as the chip + * clocks are cut and it can only be brought out of this mode + * using the RESET pin. + */ +enum pixcir_power_mode { + PIXCIR_POWER_ACTIVE, + PIXCIR_POWER_IDLE, + PIXCIR_POWER_HALT, +}; + +#define PIXCIR_POWER_MODE_MASK 0x03 +#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2) + +/* + * Interrupt modes: + * periodical: interrupt is asserted periodicaly + * diff coordinates: interrupt is asserted when coordinates change + * level on touch: interrupt level asserted during touch + * pulse on touch: interrupt pulse asserted druing touch + * + */ +enum pixcir_int_mode { + PIXCIR_INT_PERIODICAL, + PIXCIR_INT_DIFF_COORD, + PIXCIR_INT_LEVEL_TOUCH, + PIXCIR_INT_PULSE_TOUCH, +}; + +#define PIXCIR_INT_MODE_MASK 0x03 +#define PIXCIR_INT_ENABLE (1UL << 3) +#define PIXCIR_INT_POL_HIGH (1UL << 2) + +/** + * struct pixcir_irc_chip_data - chip related data + * @max_fingers: Max number of fingers reported simultaneously by h/w + * @has_hw_ids: Hardware supports finger tracking IDs + * + */ +struct pixcir_i2c_chip_data { + u8 max_fingers; + bool has_hw_ids; +}; + +struct pixcir_ts_platform_data { + int x_max; + int y_max; + int gpio_attb; /* GPIO connected to ATTB line */ + struct pixcir_i2c_chip_data chip; +}; + +#endif -- cgit v1.2.3 From cb4a5f068096c0cea954f363e70020aabb3555f4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 6 Jul 2015 11:56:21 -0700 Subject: Input: pixcir_i2c_ts - switch the device over to gpiod This allows uniform parsing on legacy, DT and ACPI systems. Acked-by: Roger Quadros Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 26 +++++++++----------------- include/linux/platform_data/pixcir_i2c_ts.h | 1 - 2 files changed, 9 insertions(+), 18 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index f7d90997a786..19732b573227 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -25,8 +25,8 @@ #include #include #include +#include #include -#include #include #include @@ -35,6 +35,7 @@ struct pixcir_i2c_ts_data { struct i2c_client *client; struct input_dev *input; + struct gpio_desc *gpio_attb; const struct pixcir_ts_platform_data *pdata; bool running; int max_fingers; /* Max fingers supported in this instance */ @@ -161,7 +162,6 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) { struct pixcir_i2c_ts_data *tsdata = dev_id; - const struct pixcir_ts_platform_data *pdata = tsdata->pdata; struct pixcir_report_data report; while (tsdata->running) { @@ -171,7 +171,7 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) /* report it */ pixcir_ts_report(tsdata, &report); - if (gpio_get_value(pdata->gpio_attb)) { + if (gpiod_get_value(tsdata->gpio_attb)) { if (report.num_touches) { /* * Last report with no finger up? @@ -427,9 +427,6 @@ static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev) pdata->chip = *(const struct pixcir_i2c_chip_data *)match->data; - pdata->gpio_attb = of_get_named_gpio(np, "attb-gpio", 0); - /* gpio_attb validity is checked in probe */ - if (of_property_read_u32(np, "touchscreen-size-x", &pdata->x_max)) { dev_err(dev, "Failed to get touchscreen-size-x property\n"); return ERR_PTR(-EINVAL); @@ -442,8 +439,8 @@ static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev) } pdata->y_max -= 1; - dev_dbg(dev, "%s: x %d, y %d, gpio %d\n", __func__, - pdata->x_max + 1, pdata->y_max + 1, pdata->gpio_attb); + dev_dbg(dev, "%s: x %d, y %d\n", __func__, + pdata->x_max + 1, pdata->y_max + 1); return pdata; } @@ -476,11 +473,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, return -EINVAL; } - if (!gpio_is_valid(pdata->gpio_attb)) { - dev_err(dev, "Invalid gpio_attb in pdata\n"); - return -EINVAL; - } - if (!pdata->chip.max_fingers) { dev_err(dev, "Invalid max_fingers in pdata\n"); return -EINVAL; @@ -530,10 +522,10 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, input_set_drvdata(input, tsdata); - error = devm_gpio_request_one(dev, pdata->gpio_attb, - GPIOF_DIR_IN, "pixcir_i2c_attb"); - if (error) { - dev_err(dev, "Failed to request ATTB gpio\n"); + tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN); + if (IS_ERR(tsdata->gpio_attb)) { + error = PTR_ERR(tsdata->gpio_attb); + dev_err(dev, "Failed to request ATTB gpio: %d\n", error); return error; } diff --git a/include/linux/platform_data/pixcir_i2c_ts.h b/include/linux/platform_data/pixcir_i2c_ts.h index 7bae83b7c396..646af6f8b838 100644 --- a/include/linux/platform_data/pixcir_i2c_ts.h +++ b/include/linux/platform_data/pixcir_i2c_ts.h @@ -57,7 +57,6 @@ struct pixcir_i2c_chip_data { struct pixcir_ts_platform_data { int x_max; int y_max; - int gpio_attb; /* GPIO connected to ATTB line */ struct pixcir_i2c_chip_data chip; }; -- cgit v1.2.3 From 527b397a7a3647b8ba2eae2e7a12b237bf411476 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 23 Jun 2015 15:48:02 +0200 Subject: gpio: em: Remove obsolete platform data support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 59032702ead90562 ("ARM: shmobile: Remove legacy platform devices from EMEV2 SoC code"), EMMA Mobile SoCs are only supported in generic DT-only ARM multi-platform builds. The driver doesn't need to use platform data anymore, hence remove platform data configuration. Signed-off-by: Geert Uytterhoeven Acked-by: Simon Horman Tested-by: Niklas Söderlund Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 34 ++++++++-------------------------- include/linux/platform_data/gpio-em.h | 11 ----------- 2 files changed, 8 insertions(+), 37 deletions(-) delete mode 100644 include/linux/platform_data/gpio-em.h (limited to 'include/linux/platform_data') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index fbf287307c4c..a77f16c8d142 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -31,7 +31,6 @@ #include #include #include -#include struct em_gio_priv { void __iomem *base0; @@ -273,13 +272,12 @@ static const struct irq_domain_ops em_gio_irq_domain_ops = { static int em_gio_probe(struct platform_device *pdev) { - struct gpio_em_config pdata_dt; - struct gpio_em_config *pdata = dev_get_platdata(&pdev->dev); struct em_gio_priv *p; struct resource *io[2], *irq[2]; struct gpio_chip *gpio_chip; struct irq_chip *irq_chip; const char *name = dev_name(&pdev->dev); + unsigned int ngpios; int ret; p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); @@ -319,18 +317,10 @@ static int em_gio_probe(struct platform_device *pdev) goto err0; } - if (!pdata) { - memset(&pdata_dt, 0, sizeof(pdata_dt)); - pdata = &pdata_dt; - - if (of_property_read_u32(pdev->dev.of_node, "ngpios", - &pdata->number_of_pins)) { - dev_err(&pdev->dev, "Missing ngpios OF property\n"); - ret = -EINVAL; - goto err0; - } - - pdata->gpio_base = -1; + if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { + dev_err(&pdev->dev, "Missing ngpios OF property\n"); + ret = -EINVAL; + goto err0; } gpio_chip = &p->gpio_chip; @@ -345,8 +335,8 @@ static int em_gio_probe(struct platform_device *pdev) gpio_chip->label = name; gpio_chip->dev = &pdev->dev; gpio_chip->owner = THIS_MODULE; - gpio_chip->base = pdata->gpio_base; - gpio_chip->ngpio = pdata->number_of_pins; + gpio_chip->base = -1; + gpio_chip->ngpio = ngpios; irq_chip = &p->irq_chip; irq_chip->name = name; @@ -357,9 +347,7 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_release_resources = em_gio_irq_relres; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; - p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, - pdata->number_of_pins, - pdata->irq_base, + p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0, &em_gio_irq_domain_ops, p); if (!p->irq_domain) { ret = -ENXIO; @@ -387,12 +375,6 @@ static int em_gio_probe(struct platform_device *pdev) goto err1; } - if (pdata->pctl_name) { - ret = gpiochip_add_pin_range(gpio_chip, pdata->pctl_name, 0, - gpio_chip->base, gpio_chip->ngpio); - if (ret < 0) - dev_warn(&pdev->dev, "failed to add pin range\n"); - } return 0; err1: diff --git a/include/linux/platform_data/gpio-em.h b/include/linux/platform_data/gpio-em.h deleted file mode 100644 index 7c5a519d2dcd..000000000000 --- a/include/linux/platform_data/gpio-em.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __GPIO_EM_H__ -#define __GPIO_EM_H__ - -struct gpio_em_config { - unsigned int gpio_base; - unsigned int irq_base; - unsigned int number_of_pins; - const char *pctl_name; -}; - -#endif /* __GPIO_EM_H__ */ -- cgit v1.2.3 From a3bd4f989f532694337dd30538b635d5213ab86a Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 22 Jul 2015 20:53:09 +0800 Subject: mmc: sdhci-esdhc-imx: clear f_max in boarddata After commit 8d86e4fcccf6 ("mmc: sdhci-esdhc-imx: Call mmc_of_parse()"), it's not used anymore. Signed-off-by: Dong Aisheng Reviewed-by: Johan Derycke Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 7 +------ include/linux/platform_data/mmc-esdhc-imx.h | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 1b0e61847e73..c6b9f6492e1a 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -581,13 +581,8 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct pltfm_imx_data *imx_data = pltfm_host->priv; - struct esdhc_platform_data *boarddata = &imx_data->boarddata; - if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock)) - return boarddata->f_max; - else - return pltfm_host->clock; + return pltfm_host->clock; } static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h index 75f70f6ac137..e1571efa3f2b 100644 --- a/include/linux/platform_data/mmc-esdhc-imx.h +++ b/include/linux/platform_data/mmc-esdhc-imx.h @@ -43,7 +43,6 @@ struct esdhc_platform_data { enum wp_types wp_type; enum cd_types cd_type; int max_bus_width; - unsigned int f_max; bool support_vsel; unsigned int delay_line; }; -- cgit v1.2.3 From fa466c91970a0207d9384016cc7884a7f61834b6 Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Wed, 22 Jul 2015 07:32:22 -0500 Subject: spi: davinci: Choose correct pre-scaler limit based on SOC Currently the pre-scaler limit is incorrect. The value differs slightly for various devices so a single value can't be used. Using the compatible field select the correct pre-scaler limit. Add new compatible field value for Keystone devices to support their unique pre-scaler limit value. Signed-off-by: Franklin S Cooper Jr Reviewed-by: Sekhar Nori Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/spi-davinci.txt | 2 + drivers/spi/spi-davinci.c | 43 ++++++++++++++++++---- include/linux/platform_data/spi-davinci.h | 1 + 3 files changed, 39 insertions(+), 7 deletions(-) (limited to 'include/linux/platform_data') diff --git a/Documentation/devicetree/bindings/spi/spi-davinci.txt b/Documentation/devicetree/bindings/spi/spi-davinci.txt index 12ecfe9e3599..d1e914adcf6e 100644 --- a/Documentation/devicetree/bindings/spi/spi-davinci.txt +++ b/Documentation/devicetree/bindings/spi/spi-davinci.txt @@ -12,6 +12,8 @@ Required properties: - compatible: - "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family - "ti,da830-spi" for SPI used similar to that on DA8xx SoC family + - "ti,keystone-spi" for SPI used similar to that on Keystone2 SoC + family - reg: Offset and length of SPI controller register space - num-cs: Number of chip selects. This includes internal as well as GPIO chip selects. diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index b4605c4158f4..3cf9faa6cc3f 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -139,6 +139,8 @@ struct davinci_spi { u32 (*get_tx)(struct davinci_spi *); u8 *bytes_per_word; + + u8 prescaler_limit; }; static struct davinci_spi_config davinci_spi_default_cfg; @@ -266,7 +268,7 @@ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, /* Subtract 1 to match what will be programmed into SPI register. */ ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz) - 1; - if (ret < 0 || ret > 255) + if (ret < dspi->prescaler_limit || ret > 255) return -EINVAL; return ret; @@ -833,13 +835,40 @@ rx_dma_failed: } #if defined(CONFIG_OF) + +/* OF SPI data structure */ +struct davinci_spi_of_data { + u8 version; + u8 prescaler_limit; +}; + +static const struct davinci_spi_of_data dm6441_spi_data = { + .version = SPI_VERSION_1, + .prescaler_limit = 2, +}; + +static const struct davinci_spi_of_data da830_spi_data = { + .version = SPI_VERSION_2, + .prescaler_limit = 2, +}; + +static const struct davinci_spi_of_data keystone_spi_data = { + .version = SPI_VERSION_1, + .prescaler_limit = 0, +}; + static const struct of_device_id davinci_spi_of_match[] = { { .compatible = "ti,dm6441-spi", + .data = &dm6441_spi_data, }, { .compatible = "ti,da830-spi", - .data = (void *)SPI_VERSION_2, + .data = &da830_spi_data, + }, + { + .compatible = "ti,keystone-spi", + .data = &keystone_spi_data, }, { }, }; @@ -858,21 +887,21 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, struct davinci_spi *dspi) { struct device_node *node = pdev->dev.of_node; + struct davinci_spi_of_data *spi_data; struct davinci_spi_platform_data *pdata; unsigned int num_cs, intr_line = 0; const struct of_device_id *match; pdata = &dspi->pdata; - pdata->version = SPI_VERSION_1; match = of_match_device(davinci_spi_of_match, &pdev->dev); if (!match) return -ENODEV; - /* match data has the SPI version number for SPI_VERSION_2 */ - if (match->data == (void *)SPI_VERSION_2) - pdata->version = SPI_VERSION_2; + spi_data = (struct davinci_spi_of_data *)match->data; + pdata->version = spi_data->version; + pdata->prescaler_limit = spi_data->prescaler_limit; /* * default num_cs is 1 and all chipsel are internal to the chip * indicated by chip_sel being NULL or cs_gpios being NULL or @@ -992,7 +1021,7 @@ static int davinci_spi_probe(struct platform_device *pdev) dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; - + dspi->prescaler_limit = pdata->prescaler_limit; dspi->version = pdata->version; dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP; diff --git a/include/linux/platform_data/spi-davinci.h b/include/linux/platform_data/spi-davinci.h index 8dc2fa47a2aa..f4edcb03c40c 100644 --- a/include/linux/platform_data/spi-davinci.h +++ b/include/linux/platform_data/spi-davinci.h @@ -49,6 +49,7 @@ struct davinci_spi_platform_data { u8 num_chipselect; u8 intr_line; u8 *chip_sel; + u8 prescaler_limit; bool cshold_bug; enum dma_event_q dma_event_q; }; -- cgit v1.2.3 From e018a0cce3d849bc73e72686c571420adc40bad2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 24 Jul 2015 21:24:04 +0300 Subject: net/macb: convert to kernel doc This patch coverts struct description to the kernel doc format. There is no functional change. Signed-off-by: Andy Shevchenko Signed-off-by: David S. Miller --- include/linux/platform_data/macb.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'include/linux/platform_data') diff --git a/include/linux/platform_data/macb.h b/include/linux/platform_data/macb.h index 044a124bfbbc..21b15f6fee25 100644 --- a/include/linux/platform_data/macb.h +++ b/include/linux/platform_data/macb.h @@ -8,11 +8,19 @@ #ifndef __MACB_PDATA_H__ #define __MACB_PDATA_H__ +/** + * struct macb_platform_data - platform data for MACB Ethernet + * @phy_mask: phy mask passed when register the MDIO bus + * within the driver + * @phy_irq_pin: PHY IRQ + * @is_rmii: using RMII interface? + * @rev_eth_addr: reverse Ethernet address byte order + */ struct macb_platform_data { u32 phy_mask; - int phy_irq_pin; /* PHY IRQ */ - u8 is_rmii; /* using RMII interface? */ - u8 rev_eth_addr; /* reverse Ethernet address byte order */ + int phy_irq_pin; + u8 is_rmii; + u8 rev_eth_addr; }; #endif /* __MACB_PDATA_H__ */ -- cgit v1.2.3 From 7f3884f7de89c49439fdaa115f6d1caec3256cc3 Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Tue, 4 Aug 2015 16:36:29 -0700 Subject: Input: atmel_mxt_ts - use deep sleep mode when stopped The hardcoded 0x83 CTRL setting overrides other settings in that byte, enabling extra reporting that may not be useful on a particular platform. Implement improved suspend mechanism via deep sleep. By writing zero to both the active and idle cycle times the maXTouch device can be put into a deep sleep mode, using minimal power. It is necessary to issue a calibrate command after the chip has spent any time in deep sleep, however a soft reset is unnecessary. Use the old method on Chromebook Pixel via platform data option. This patch also deals with the situation where the power configuration is zero on probe, which would mean that the device never wakes up to execute commands. After a config download, the T7 power configuration may have changed so it is necessary to re-read it. Signed-off-by: Nick Dyer Acked-by: Benson Leung Acked-by: Yufeng Shen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 119 ++++++++++++++++++++++++++--- drivers/platform/chrome/chromeos_laptop.c | 4 +- include/linux/i2c/atmel_mxt_ts.h | 25 ------ include/linux/platform_data/atmel_mxt_ts.h | 31 ++++++++ 4 files changed, 142 insertions(+), 37 deletions(-) delete mode 100644 include/linux/i2c/atmel_mxt_ts.h create mode 100644 include/linux/platform_data/atmel_mxt_ts.h (limited to 'include/linux/platform_data') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 8efe7a002f1e..0e743b3a691b 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -103,9 +103,13 @@ #define MXT_T6_STATUS_COMSERR (1 << 2) /* MXT_GEN_POWER_T7 field */ -#define MXT_POWER_IDLEACQINT 0 -#define MXT_POWER_ACTVACQINT 1 -#define MXT_POWER_ACTV2IDLETO 2 +struct t7_config { + u8 idle; + u8 active; +} __packed; + +#define MXT_POWER_CFG_RUN 0 +#define MXT_POWER_CFG_DEEPSLEEP 1 /* MXT_GEN_ACQUIRE_T8 field */ #define MXT_ACQUIRE_CHRGTIME 0 @@ -117,7 +121,7 @@ #define MXT_ACQUIRE_ATCHCALSTHR 7 /* MXT_TOUCH_MULTI_T9 field */ -#define MXT_TOUCH_CTRL 0 +#define MXT_T9_CTRL 0 #define MXT_T9_ORIENT 9 #define MXT_T9_RANGE 18 @@ -291,6 +295,7 @@ struct mxt_data { u8 last_message_count; u8 num_touchids; u8 multitouch; + struct t7_config t7_cfg; /* Cached parameters from object table */ u16 T5_address; @@ -1361,6 +1366,8 @@ static int mxt_upload_cfg_mem(struct mxt_data *data, unsigned int cfg_start, return 0; } +static int mxt_init_t7_power_cfg(struct mxt_data *data); + /* * mxt_update_cfg - download configuration to chip * @@ -1508,6 +1515,9 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) dev_info(dev, "Config successfully updated\n"); + /* T7 config may have changed */ + mxt_init_t7_power_cfg(data); + release_mem: kfree(config_mem); return ret; @@ -2051,6 +2061,60 @@ err_free_object_table: return error; } +static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) +{ + struct device *dev = &data->client->dev; + int error; + struct t7_config *new_config; + struct t7_config deepsleep = { .active = 0, .idle = 0 }; + + if (sleep == MXT_POWER_CFG_DEEPSLEEP) + new_config = &deepsleep; + else + new_config = &data->t7_cfg; + + error = __mxt_write_reg(data->client, data->T7_address, + sizeof(data->t7_cfg), new_config); + if (error) + return error; + + dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n", + new_config->active, new_config->idle); + + return 0; +} + +static int mxt_init_t7_power_cfg(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + int error; + bool retry = false; + +recheck: + error = __mxt_read_reg(data->client, data->T7_address, + sizeof(data->t7_cfg), &data->t7_cfg); + if (error) + return error; + + if (data->t7_cfg.active == 0 || data->t7_cfg.idle == 0) { + if (!retry) { + dev_dbg(dev, "T7 cfg zero, resetting\n"); + mxt_soft_reset(data); + retry = true; + goto recheck; + } else { + dev_dbg(dev, "T7 cfg zero after reset, overriding\n"); + data->t7_cfg.active = 20; + data->t7_cfg.idle = 100; + return mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); + } + } + + dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d\n", + data->t7_cfg.active, data->t7_cfg.idle); + return 0; +} + static int mxt_configure_objects(struct mxt_data *data, const struct firmware *cfg) { @@ -2058,6 +2122,12 @@ static int mxt_configure_objects(struct mxt_data *data, struct mxt_info *info = &data->info; int error; + error = mxt_init_t7_power_cfg(data); + if (error) { + dev_err(dev, "Failed to initialize power cfg\n"); + return error; + } + if (cfg) { error = mxt_update_cfg(data, cfg); if (error) @@ -2346,14 +2416,41 @@ static const struct attribute_group mxt_attr_group = { static void mxt_start(struct mxt_data *data) { - /* Touch enable */ - mxt_write_object(data, data->multitouch, MXT_TOUCH_CTRL, 0x83); + switch (data->pdata->suspend_mode) { + case MXT_SUSPEND_T9_CTRL: + mxt_soft_reset(data); + + /* Touch enable */ + /* 0x83 = SCANEN | RPTEN | ENABLE */ + mxt_write_object(data, + MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0x83); + break; + + case MXT_SUSPEND_DEEP_SLEEP: + default: + mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); + + /* Recalibrate since chip has been in deep sleep */ + mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false); + break; + } + } static void mxt_stop(struct mxt_data *data) { - /* Touch disable */ - mxt_write_object(data, data->multitouch, MXT_TOUCH_CTRL, 0); + switch (data->pdata->suspend_mode) { + case MXT_SUSPEND_T9_CTRL: + /* Touch disable */ + mxt_write_object(data, + MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0); + break; + + case MXT_SUSPEND_DEEP_SLEEP: + default: + mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP); + break; + } } static int mxt_input_open(struct input_dev *dev) @@ -2409,6 +2506,8 @@ static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) pdata->t19_keymap = keymap; } + pdata->suspend_mode = MXT_SUSPEND_DEEP_SLEEP; + return pdata; } #else @@ -2625,8 +2724,6 @@ static int __maybe_unused mxt_resume(struct device *dev) struct mxt_data *data = i2c_get_clientdata(client); struct input_dev *input_dev = data->input_dev; - mxt_soft_reset(data); - mutex_lock(&input_dev->mutex); if (input_dev->users) diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index a04019ab9feb..02072749fff3 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include @@ -111,6 +111,7 @@ static struct mxt_platform_data atmel_224s_tp_platform_data = { .irqflags = IRQF_TRIGGER_FALLING, .t19_num_keys = ARRAY_SIZE(mxt_t19_keys), .t19_keymap = mxt_t19_keys, + .suspend_mode = MXT_SUSPEND_T9_CTRL, }; static struct i2c_board_info atmel_224s_tp_device = { @@ -121,6 +122,7 @@ static struct i2c_board_info atmel_224s_tp_device = { static struct mxt_platform_data atmel_1664s_platform_data = { .irqflags = IRQF_TRIGGER_FALLING, + .suspend_mode = MXT_SUSPEND_T9_CTRL, }; static struct i2c_board_info atmel_1664s_device = { diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h deleted file mode 100644 index 02bf6ea31701..000000000000 --- a/include/linux/i2c/atmel_mxt_ts.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Atmel maXTouch Touchscreen driver - * - * Copyright (C) 2010 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef __LINUX_ATMEL_MXT_TS_H -#define __LINUX_ATMEL_MXT_TS_H - -#include - -/* The platform data for the Atmel maXTouch touchscreen driver */ -struct mxt_platform_data { - unsigned long irqflags; - u8 t19_num_keys; - const unsigned int *t19_keymap; -}; - -#endif /* __LINUX_ATMEL_MXT_TS_H */ diff --git a/include/linux/platform_data/atmel_mxt_ts.h b/include/linux/platform_data/atmel_mxt_ts.h new file mode 100644 index 000000000000..695035a8d7fb --- /dev/null +++ b/include/linux/platform_data/atmel_mxt_ts.h @@ -0,0 +1,31 @@ +/* + * Atmel maXTouch Touchscreen driver + * + * Copyright (C) 2010 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H +#define __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H + +#include + +enum mxt_suspend_mode { + MXT_SUSPEND_DEEP_SLEEP = 0, + MXT_SUSPEND_T9_CTRL = 1, +}; + +/* The platform data for the Atmel maXTouch touchscreen driver */ +struct mxt_platform_data { + unsigned long irqflags; + u8 t19_num_keys; + const unsigned int *t19_keymap; + enum mxt_suspend_mode suspend_mode; +}; + +#endif /* __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H */ -- cgit v1.2.3 From a568231f463225eb31593f71446a267a03ae0528 Mon Sep 17 00:00:00 2001 From: Leilk Liu Date: Fri, 7 Aug 2015 15:19:50 +0800 Subject: spi: mediatek: Add spi bus for Mediatek MT8173 This patch adds basic spi bus for MT8173. Signed-off-by: Leilk Liu Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-mt65xx.c | 749 +++++++++++++++++++++++++++++++ include/linux/platform_data/spi-mt65xx.h | 22 + 4 files changed, 781 insertions(+) create mode 100644 drivers/spi/spi-mt65xx.c create mode 100644 include/linux/platform_data/spi-mt65xx.h (limited to 'include/linux/platform_data') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 0cae1694014d..38ddfba49d76 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -326,6 +326,15 @@ config SPI_MESON_SPIFC This enables master mode support for the SPIFC (SPI flash controller) available in Amlogic Meson SoCs. +config SPI_MT65XX + tristate "MediaTek SPI controller" + depends on ARCH_MEDIATEK || COMPILE_TEST + help + This selects the MediaTek(R) SPI bus driver. + If you want to use MediaTek(R) SPI interface, + say Y or M here.If you are not sure, say N. + SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. + config SPI_OC_TINY tristate "OpenCores tiny SPI" depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 1154dbac8f2c..9746beb21769 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o +obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c new file mode 100644 index 000000000000..4676b0122b89 --- /dev/null +++ b/drivers/spi/spi-mt65xx.c @@ -0,0 +1,749 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: Leilk Liu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPI_CFG0_REG 0x0000 +#define SPI_CFG1_REG 0x0004 +#define SPI_TX_SRC_REG 0x0008 +#define SPI_RX_DST_REG 0x000c +#define SPI_TX_DATA_REG 0x0010 +#define SPI_RX_DATA_REG 0x0014 +#define SPI_CMD_REG 0x0018 +#define SPI_STATUS0_REG 0x001c +#define SPI_PAD_SEL_REG 0x0024 + +#define SPI_CFG0_SCK_HIGH_OFFSET 0 +#define SPI_CFG0_SCK_LOW_OFFSET 8 +#define SPI_CFG0_CS_HOLD_OFFSET 16 +#define SPI_CFG0_CS_SETUP_OFFSET 24 + +#define SPI_CFG1_CS_IDLE_OFFSET 0 +#define SPI_CFG1_PACKET_LOOP_OFFSET 8 +#define SPI_CFG1_PACKET_LENGTH_OFFSET 16 +#define SPI_CFG1_GET_TICK_DLY_OFFSET 30 + +#define SPI_CFG1_CS_IDLE_MASK 0xff +#define SPI_CFG1_PACKET_LOOP_MASK 0xff00 +#define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000 + +#define SPI_CMD_ACT_OFFSET 0 +#define SPI_CMD_RESUME_OFFSET 1 +#define SPI_CMD_CPHA_OFFSET 8 +#define SPI_CMD_CPOL_OFFSET 9 +#define SPI_CMD_TXMSBF_OFFSET 12 +#define SPI_CMD_RXMSBF_OFFSET 13 +#define SPI_CMD_RX_ENDIAN_OFFSET 14 +#define SPI_CMD_TX_ENDIAN_OFFSET 15 + +#define SPI_CMD_RST BIT(2) +#define SPI_CMD_PAUSE_EN BIT(4) +#define SPI_CMD_DEASSERT BIT(5) +#define SPI_CMD_CPHA BIT(8) +#define SPI_CMD_CPOL BIT(9) +#define SPI_CMD_RX_DMA BIT(10) +#define SPI_CMD_TX_DMA BIT(11) +#define SPI_CMD_TXMSBF BIT(12) +#define SPI_CMD_RXMSBF BIT(13) +#define SPI_CMD_RX_ENDIAN BIT(14) +#define SPI_CMD_TX_ENDIAN BIT(15) +#define SPI_CMD_FINISH_IE BIT(16) +#define SPI_CMD_PAUSE_IE BIT(17) + +#define MTK_SPI_QUIRK_PAD_SELECT 1 +/* Must explicitly send dummy Tx bytes to do Rx only transfer */ +#define MTK_SPI_QUIRK_MUST_TX 1 + +#define MT8173_SPI_MAX_PAD_SEL 3 + +#define MTK_SPI_IDLE 0 +#define MTK_SPI_PAUSED 1 + +#define MTK_SPI_MAX_FIFO_SIZE 32 +#define MTK_SPI_PACKET_SIZE 1024 + +struct mtk_spi_compatible { + u32 need_pad_sel; + u32 must_tx; +}; + +struct mtk_spi { + void __iomem *base; + u32 state; + u32 pad_sel; + struct clk *spi_clk, *parent_clk; + struct spi_transfer *cur_transfer; + u32 xfer_len; + struct scatterlist *tx_sgl, *rx_sgl; + u32 tx_sgl_len, rx_sgl_len; + const struct mtk_spi_compatible *dev_comp; +}; + +static const struct mtk_spi_compatible mt6589_compat = { + .need_pad_sel = 0, + .must_tx = 0, +}; + +static const struct mtk_spi_compatible mt8135_compat = { + .need_pad_sel = 0, + .must_tx = 0, +}; + +static const struct mtk_spi_compatible mt8173_compat = { + .need_pad_sel = MTK_SPI_QUIRK_PAD_SELECT, + .must_tx = MTK_SPI_QUIRK_MUST_TX, +}; + +/* + * A piece of default chip info unless the platform + * supplies it. + */ +static const struct mtk_chip_config mtk_default_chip_info = { + .rx_mlsb = 1, + .tx_mlsb = 1, + .tx_endian = 0, + .rx_endian = 0, +}; + +static const struct of_device_id mtk_spi_of_match[] = { + { .compatible = "mediatek,mt6589-spi", .data = (void *)&mt6589_compat }, + { .compatible = "mediatek,mt8135-spi", .data = (void *)&mt8135_compat }, + { .compatible = "mediatek,mt8173-spi", .data = (void *)&mt8173_compat }, + {} +}; +MODULE_DEVICE_TABLE(of, mtk_spi_of_match); + +static void mtk_spi_reset(struct mtk_spi *mdata) +{ + u32 reg_val; + + /* set the software reset bit in SPI_CMD_REG. */ + reg_val = readl(mdata->base + SPI_CMD_REG); + reg_val |= SPI_CMD_RST; + writel(reg_val, mdata->base + SPI_CMD_REG); + + reg_val = readl(mdata->base + SPI_CMD_REG); + reg_val &= ~SPI_CMD_RST; + writel(reg_val, mdata->base + SPI_CMD_REG); +} + +static void mtk_spi_config(struct mtk_spi *mdata, + struct mtk_chip_config *chip_config) +{ + u32 reg_val; + + reg_val = readl(mdata->base + SPI_CMD_REG); + + /* set the mlsbx and mlsbtx */ + reg_val &= ~(SPI_CMD_TXMSBF | SPI_CMD_RXMSBF); + reg_val |= (chip_config->tx_mlsb << SPI_CMD_TXMSBF_OFFSET); + reg_val |= (chip_config->rx_mlsb << SPI_CMD_RXMSBF_OFFSET); + + /* set the tx/rx endian */ + reg_val &= ~(SPI_CMD_TX_ENDIAN | SPI_CMD_RX_ENDIAN); + reg_val |= (chip_config->tx_endian << SPI_CMD_TX_ENDIAN_OFFSET); + reg_val |= (chip_config->rx_endian << SPI_CMD_RX_ENDIAN_OFFSET); + + /* set finish and pause interrupt always enable */ + reg_val |= SPI_CMD_FINISH_IE | SPI_CMD_PAUSE_EN; + + /* disable dma mode */ + reg_val &= ~(SPI_CMD_TX_DMA | SPI_CMD_RX_DMA); + + /* disable deassert mode */ + reg_val &= ~SPI_CMD_DEASSERT; + + writel(reg_val, mdata->base + SPI_CMD_REG); + + /* pad select */ + if (mdata->dev_comp->need_pad_sel) + writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG); +} + +static int mtk_spi_prepare_hardware(struct spi_master *master) +{ + struct spi_transfer *trans; + struct mtk_spi *mdata = spi_master_get_devdata(master); + struct spi_message *msg = master->cur_msg; + int ret; + + ret = clk_prepare_enable(mdata->spi_clk); + if (ret < 0) { + dev_err(&master->dev, "failed to enable clock (%d)\n", ret); + return ret; + } + + trans = list_first_entry(&msg->transfers, struct spi_transfer, + transfer_list); + if (trans->cs_change == 0) { + mdata->state = MTK_SPI_IDLE; + mtk_spi_reset(mdata); + } + + return ret; +} + +static int mtk_spi_unprepare_hardware(struct spi_master *master) +{ + struct mtk_spi *mdata = spi_master_get_devdata(master); + + clk_disable_unprepare(mdata->spi_clk); + + return 0; +} + +static int mtk_spi_prepare_message(struct spi_master *master, + struct spi_message *msg) +{ + u32 reg_val; + u8 cpha, cpol; + struct mtk_chip_config *chip_config; + struct spi_device *spi = msg->spi; + struct mtk_spi *mdata = spi_master_get_devdata(master); + + cpha = spi->mode & SPI_CPHA ? 1 : 0; + cpol = spi->mode & SPI_CPOL ? 1 : 0; + + reg_val = readl(mdata->base + SPI_CMD_REG); + reg_val &= ~(SPI_CMD_CPHA | SPI_CMD_CPOL); + reg_val |= (cpha << SPI_CMD_CPHA_OFFSET); + reg_val |= (cpol << SPI_CMD_CPOL_OFFSET); + writel(reg_val, mdata->base + SPI_CMD_REG); + + chip_config = spi->controller_data; + if (!chip_config) { + chip_config = (void *)&mtk_default_chip_info; + spi->controller_data = chip_config; + } + mtk_spi_config(mdata, chip_config); + + return 0; +} + +static void mtk_spi_set_cs(struct spi_device *spi, bool enable) +{ + u32 reg_val; + struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + + reg_val = readl(mdata->base + SPI_CMD_REG); + if (!enable) + reg_val |= SPI_CMD_PAUSE_EN; + else + reg_val &= ~SPI_CMD_PAUSE_EN; + writel(reg_val, mdata->base + SPI_CMD_REG); +} + +static void mtk_spi_prepare_transfer(struct spi_master *master, + struct spi_transfer *xfer) +{ + u32 spi_clk_hz, div, high_time, low_time, holdtime, + setuptime, cs_idletime, reg_val = 0; + struct mtk_spi *mdata = spi_master_get_devdata(master); + + spi_clk_hz = clk_get_rate(mdata->spi_clk); + if (xfer->speed_hz < spi_clk_hz / 2) + div = DIV_ROUND_UP(spi_clk_hz, xfer->speed_hz); + else + div = 1; + + high_time = (div + 1) / 2; + low_time = (div + 1) / 2; + holdtime = (div + 1) / 2 * 2; + setuptime = (div + 1) / 2 * 2; + cs_idletime = (div + 1) / 2 * 2; + + reg_val |= (((high_time - 1) & 0xff) << SPI_CFG0_SCK_HIGH_OFFSET); + reg_val |= (((low_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET); + reg_val |= (((holdtime - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET); + reg_val |= (((setuptime - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET); + writel(reg_val, mdata->base + SPI_CFG0_REG); + + reg_val = readl(mdata->base + SPI_CFG1_REG); + reg_val &= ~SPI_CFG1_CS_IDLE_MASK; + reg_val |= (((cs_idletime - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET); + writel(reg_val, mdata->base + SPI_CFG1_REG); +} + +static void mtk_spi_setup_packet(struct spi_master *master) +{ + u32 packet_size, packet_loop, reg_val; + struct mtk_spi *mdata = spi_master_get_devdata(master); + + packet_size = min_t(unsigned, mdata->xfer_len, MTK_SPI_PACKET_SIZE); + packet_loop = mdata->xfer_len / packet_size; + + reg_val = readl(mdata->base + SPI_CFG1_REG); + reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK + SPI_CFG1_PACKET_LOOP_MASK); + reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET; + reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET; + writel(reg_val, mdata->base + SPI_CFG1_REG); +} + +static void mtk_spi_enable_transfer(struct spi_master *master) +{ + int cmd; + struct mtk_spi *mdata = spi_master_get_devdata(master); + + cmd = readl(mdata->base + SPI_CMD_REG); + if (mdata->state == MTK_SPI_IDLE) + cmd |= 1 << SPI_CMD_ACT_OFFSET; + else + cmd |= 1 << SPI_CMD_RESUME_OFFSET; + writel(cmd, mdata->base + SPI_CMD_REG); +} + +static int mtk_spi_get_mult_delta(int xfer_len) +{ + int mult_delta; + + if (xfer_len > MTK_SPI_PACKET_SIZE) + mult_delta = xfer_len % MTK_SPI_PACKET_SIZE; + else + mult_delta = 0; + + return mult_delta; +} + +static void mtk_spi_update_mdata_len(struct spi_master *master) +{ + int mult_delta; + struct mtk_spi *mdata = spi_master_get_devdata(master); + + if (mdata->tx_sgl_len && mdata->rx_sgl_len) { + if (mdata->tx_sgl_len > mdata->rx_sgl_len) { + mult_delta = mtk_spi_get_mult_delta(mdata->rx_sgl_len); + mdata->xfer_len = mdata->rx_sgl_len - mult_delta; + mdata->rx_sgl_len = mult_delta; + mdata->tx_sgl_len -= mdata->xfer_len; + } else { + mult_delta = mtk_spi_get_mult_delta(mdata->tx_sgl_len); + mdata->xfer_len = mdata->tx_sgl_len - mult_delta; + mdata->tx_sgl_len = mult_delta; + mdata->rx_sgl_len -= mdata->xfer_len; + } + } else if (mdata->tx_sgl_len) { + mult_delta = mtk_spi_get_mult_delta(mdata->tx_sgl_len); + mdata->xfer_len = mdata->tx_sgl_len - mult_delta; + mdata->tx_sgl_len = mult_delta; + } else if (mdata->rx_sgl_len) { + mult_delta = mtk_spi_get_mult_delta(mdata->rx_sgl_len); + mdata->xfer_len = mdata->rx_sgl_len - mult_delta; + mdata->rx_sgl_len = mult_delta; + } +} + +static void mtk_spi_setup_dma_addr(struct spi_master *master, + struct spi_transfer *xfer) +{ + struct mtk_spi *mdata = spi_master_get_devdata(master); + + if (mdata->tx_sgl) + writel(cpu_to_le32(xfer->tx_dma), mdata->base + SPI_TX_SRC_REG); + if (mdata->rx_sgl) + writel(cpu_to_le32(xfer->rx_dma), mdata->base + SPI_RX_DST_REG); +} + +static int mtk_spi_fifo_transfer(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + int cnt, i; + struct mtk_spi *mdata = spi_master_get_devdata(master); + + mdata->cur_transfer = xfer; + mdata->xfer_len = xfer->len; + mtk_spi_prepare_transfer(master, xfer); + mtk_spi_setup_packet(master); + + if (xfer->len % 4) + cnt = xfer->len / 4 + 1; + else + cnt = xfer->len / 4; + + for (i = 0; i < cnt; i++) + writel(*((u32 *)xfer->tx_buf + i), + mdata->base + SPI_TX_DATA_REG); + + mtk_spi_enable_transfer(master); + + return 1; +} + +static int mtk_spi_dma_transfer(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + int cmd; + struct mtk_spi *mdata = spi_master_get_devdata(master); + + mdata->tx_sgl = NULL; + mdata->rx_sgl = NULL; + mdata->tx_sgl_len = 0; + mdata->rx_sgl_len = 0; + mdata->cur_transfer = xfer; + + mtk_spi_prepare_transfer(master, xfer); + + cmd = readl(mdata->base + SPI_CMD_REG); + if (xfer->tx_buf) + cmd |= SPI_CMD_TX_DMA; + if (xfer->rx_buf) + cmd |= SPI_CMD_RX_DMA; + writel(cmd, mdata->base + SPI_CMD_REG); + + if (xfer->tx_buf) + mdata->tx_sgl = xfer->tx_sg.sgl; + if (xfer->rx_buf) + mdata->rx_sgl = xfer->rx_sg.sgl; + + if (mdata->tx_sgl) { + xfer->tx_dma = sg_dma_address(mdata->tx_sgl); + mdata->tx_sgl_len = sg_dma_len(mdata->tx_sgl); + } + if (mdata->rx_sgl) { + xfer->rx_dma = sg_dma_address(mdata->rx_sgl); + mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl); + } + + mtk_spi_update_mdata_len(master); + mtk_spi_setup_packet(master); + mtk_spi_setup_dma_addr(master, xfer); + mtk_spi_enable_transfer(master); + + return 1; +} + +static int mtk_spi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + if (master->can_dma(master, spi, xfer)) + return mtk_spi_dma_transfer(master, spi, xfer); + else + return mtk_spi_fifo_transfer(master, spi, xfer); +} + +static bool mtk_spi_can_dma(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + return xfer->len > MTK_SPI_MAX_FIFO_SIZE; +} + +static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) +{ + u32 cmd, reg_val, i; + struct spi_master *master = dev_id; + struct mtk_spi *mdata = spi_master_get_devdata(master); + struct spi_transfer *trans = mdata->cur_transfer; + + reg_val = readl(mdata->base + SPI_STATUS0_REG); + if (reg_val & 0x2) + mdata->state = MTK_SPI_PAUSED; + else + mdata->state = MTK_SPI_IDLE; + + if (!master->can_dma(master, master->cur_msg->spi, trans)) { + /* xfer len is not N*4 bytes every time in a transfer, + * but SPI_RX_DATA_REG must reads 4 bytes once, + * so rx buffer byte by byte. + */ + if (trans->rx_buf) { + for (i = 0; i < mdata->xfer_len; i++) { + if (i % 4 == 0) + reg_val = + readl(mdata->base + SPI_RX_DATA_REG); + *((u8 *)(trans->rx_buf + i)) = + (reg_val >> ((i % 4) * 8)) & 0xff; + } + } + spi_finalize_current_transfer(master); + return IRQ_HANDLED; + } + + if (mdata->tx_sgl) + trans->tx_dma += mdata->xfer_len; + if (mdata->rx_sgl) + trans->rx_dma += mdata->xfer_len; + + if (mdata->tx_sgl && (mdata->tx_sgl_len == 0)) { + mdata->tx_sgl = sg_next(mdata->tx_sgl); + if (mdata->tx_sgl) { + trans->tx_dma = sg_dma_address(mdata->tx_sgl); + mdata->tx_sgl_len = sg_dma_len(mdata->tx_sgl); + } + } + if (mdata->rx_sgl && (mdata->rx_sgl_len == 0)) { + mdata->rx_sgl = sg_next(mdata->rx_sgl); + if (mdata->rx_sgl) { + trans->rx_dma = sg_dma_address(mdata->rx_sgl); + mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl); + } + } + + if (!mdata->tx_sgl && !mdata->rx_sgl) { + /* spi disable dma */ + cmd = readl(mdata->base + SPI_CMD_REG); + cmd &= ~SPI_CMD_TX_DMA; + cmd &= ~SPI_CMD_RX_DMA; + writel(cmd, mdata->base + SPI_CMD_REG); + + spi_finalize_current_transfer(master); + return IRQ_HANDLED; + } + + mtk_spi_update_mdata_len(master); + mtk_spi_setup_packet(master); + mtk_spi_setup_dma_addr(master, trans); + mtk_spi_enable_transfer(master); + + return IRQ_HANDLED; +} + +static int mtk_spi_probe(struct platform_device *pdev) +{ + struct spi_master *master; + struct mtk_spi *mdata; + const struct of_device_id *of_id; + struct resource *res; + int irq, ret; + + master = spi_alloc_master(&pdev->dev, sizeof(*mdata)); + if (!master) { + dev_err(&pdev->dev, "failed to alloc spi master\n"); + return -ENOMEM; + } + + master->auto_runtime_pm = true; + master->dev.of_node = pdev->dev.of_node; + master->mode_bits = SPI_CPOL | SPI_CPHA; + + master->set_cs = mtk_spi_set_cs; + master->prepare_transfer_hardware = mtk_spi_prepare_hardware; + master->unprepare_transfer_hardware = mtk_spi_unprepare_hardware; + master->prepare_message = mtk_spi_prepare_message; + master->transfer_one = mtk_spi_transfer_one; + master->can_dma = mtk_spi_can_dma; + + of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node); + if (!of_id) { + dev_err(&pdev->dev, "failed to probe of_node\n"); + ret = -EINVAL; + goto err_put_master; + } + + mdata = spi_master_get_devdata(master); + mdata->dev_comp = of_id->data; + if (mdata->dev_comp->must_tx) + master->flags = SPI_MASTER_MUST_TX; + + if (mdata->dev_comp->need_pad_sel) { + ret = of_property_read_u32(pdev->dev.of_node, + "mediatek,pad-select", + &mdata->pad_sel); + if (ret) { + dev_err(&pdev->dev, "failed to read pad select: %d\n", + ret); + goto err_put_master; + } + + if (mdata->pad_sel > MT8173_SPI_MAX_PAD_SEL) { + dev_err(&pdev->dev, "wrong pad-select: %u\n", + mdata->pad_sel); + ret = -EINVAL; + goto err_put_master; + } + } + + platform_set_drvdata(pdev, master); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + dev_err(&pdev->dev, "failed to determine base address\n"); + goto err_put_master; + } + + mdata->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mdata->base)) { + ret = PTR_ERR(mdata->base); + goto err_put_master; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); + ret = irq; + goto err_put_master; + } + + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; + + ret = devm_request_irq(&pdev->dev, irq, mtk_spi_interrupt, + IRQF_TRIGGER_NONE, dev_name(&pdev->dev), master); + if (ret) { + dev_err(&pdev->dev, "failed to register irq (%d)\n", ret); + goto err_put_master; + } + + mdata->spi_clk = devm_clk_get(&pdev->dev, "spi-clk"); + if (IS_ERR(mdata->spi_clk)) { + ret = PTR_ERR(mdata->spi_clk); + dev_err(&pdev->dev, "failed to get spi-clk: %d\n", ret); + goto err_put_master; + } + + mdata->parent_clk = devm_clk_get(&pdev->dev, "parent-clk"); + if (IS_ERR(mdata->parent_clk)) { + ret = PTR_ERR(mdata->parent_clk); + dev_err(&pdev->dev, "failed to get parent-clk: %d\n", ret); + goto err_put_master; + } + + ret = clk_prepare_enable(mdata->spi_clk); + if (ret < 0) { + dev_err(&pdev->dev, "failed to enable spi_clk (%d)\n", ret); + goto err_put_master; + } + + ret = clk_set_parent(mdata->spi_clk, mdata->parent_clk); + if (ret < 0) { + dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret); + goto err_disable_clk; + } + + clk_disable_unprepare(mdata->spi_clk); + + pm_runtime_enable(&pdev->dev); + + ret = devm_spi_register_master(&pdev->dev, master); + if (ret) { + dev_err(&pdev->dev, "failed to register master (%d)\n", ret); + goto err_put_master; + } + + return 0; + +err_disable_clk: + clk_disable_unprepare(mdata->spi_clk); +err_put_master: + spi_master_put(master); + + return ret; +} + +static int mtk_spi_remove(struct platform_device *pdev) +{ + struct spi_master *master = platform_get_drvdata(pdev); + struct mtk_spi *mdata = spi_master_get_devdata(master); + + pm_runtime_disable(&pdev->dev); + + mtk_spi_reset(mdata); + clk_disable_unprepare(mdata->spi_clk); + spi_master_put(master); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mtk_spi_suspend(struct device *dev) +{ + int ret; + struct spi_master *master = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_master_get_devdata(master); + + ret = spi_master_suspend(master); + if (ret) + return ret; + + if (!pm_runtime_suspended(dev)) + clk_disable_unprepare(mdata->spi_clk); + + return ret; +} + +static int mtk_spi_resume(struct device *dev) +{ + int ret; + struct spi_master *master = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_master_get_devdata(master); + + if (!pm_runtime_suspended(dev)) { + ret = clk_prepare_enable(mdata->spi_clk); + if (ret < 0) + return ret; + } + + ret = spi_master_resume(master); + if (ret < 0) + clk_disable_unprepare(mdata->spi_clk); + + return ret; +} +#endif /* CONFIG_PM_SLEEP */ + +#ifdef CONFIG_PM +static int mtk_spi_runtime_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_master_get_devdata(master); + + clk_disable_unprepare(mdata->spi_clk); + + return 0; +} + +static int mtk_spi_runtime_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_master_get_devdata(master); + + return clk_prepare_enable(mdata->spi_clk); +} +#endif /* CONFIG_PM */ + +static const struct dev_pm_ops mtk_spi_pm = { + SET_SYSTEM_SLEEP_PM_OPS(mtk_spi_suspend, mtk_spi_resume) + SET_RUNTIME_PM_OPS(mtk_spi_runtime_suspend, + mtk_spi_runtime_resume, NULL) +}; + +struct platform_driver mtk_spi_driver = { + .driver = { + .name = "mtk-spi", + .pm = &mtk_spi_pm, + .of_match_table = mtk_spi_of_match, + }, + .probe = mtk_spi_probe, + .remove = mtk_spi_remove, +}; + +module_platform_driver(mtk_spi_driver); + +MODULE_DESCRIPTION("MTK SPI Controller driver"); +MODULE_AUTHOR("Leilk Liu "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform: mtk_spi"); diff --git a/include/linux/platform_data/spi-mt65xx.h b/include/linux/platform_data/spi-mt65xx.h new file mode 100644 index 000000000000..751225569d27 --- /dev/null +++ b/include/linux/platform_data/spi-mt65xx.h @@ -0,0 +1,22 @@ +/* + * MTK SPI bus driver definitions + * + * Copyright (c) 2015 MediaTek Inc. + * Author: Leilk Liu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H +#define ____LINUX_PLATFORM_DATA_SPI_MTK_H + +/* Board specific platform_data */ +struct mtk_chip_config { + u32 tx_mlsb; + u32 rx_mlsb; + u32 tx_endian; + u32 rx_endian; +}; +#endif -- cgit v1.2.3 From 420b54de25828c45f3fc1f12d52d9657f5e90a53 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 6 Aug 2015 13:46:24 +0100 Subject: mfd: watchdog: iTCO_wdt: Expose watchdog properties using platform data Intel Sunrisepoint (Skylake PCH) has the iTCO watchdog accessible across the SMBus, unlike previous generations of PCH/ICH where it was on the LPC bus. Because it's on the SMBus, it doesn't make sense to pass around a 'struct lpc_ich_info', and leaking the type of bus into the iTCO watchdog driver is kind of backwards anyway. This change introduces a new 'struct itco_wdt_platform_data' for use inside the iTCO watchdog driver and by the upcoming Intel Sunrisepoint code, which neatly avoids having to include lpc_ich headers in the i801 i2c driver. This change is overdue because lpc_ich_info has already found its way into other TCO watchdog users, notably the intel_pmc_ipc driver where the watchdog actually isn't on the LPC bus as far as I can see. A simple translation layer is provided for converting from the existing 'struct lpc_ich_info' inside the lpc_ich mfd driver. Signed-off-by: Matt Fleming Acked-by: Darren Hart [drivers/x86 refactoring] Reviewed-by: Guenter Roeck Signed-off-by: Lee Jones --- drivers/mfd/lpc_ich.c | 32 +++++++++++++++++++++++++++++--- drivers/platform/x86/intel_pmc_ipc.c | 9 ++++----- drivers/watchdog/iTCO_wdt.c | 11 +++++------ include/linux/mfd/lpc_ich.h | 6 ------ include/linux/platform_data/itco_wdt.h | 19 +++++++++++++++++++ 5 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 include/linux/platform_data/itco_wdt.h (limited to 'include/linux/platform_data') diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 8de34398abc0..c5a9a08b5dfb 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -66,6 +66,7 @@ #include #include #include +#include #define ACPIBASE 0x40 #define ACPIBASE_GPE_OFF 0x28 @@ -835,9 +836,31 @@ static void lpc_ich_enable_pmc_space(struct pci_dev *dev) priv->actrl_pbase_save = reg_save; } -static void lpc_ich_finalize_cell(struct pci_dev *dev, struct mfd_cell *cell) +static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev) { + struct itco_wdt_platform_data *pdata; struct lpc_ich_priv *priv = pci_get_drvdata(dev); + struct lpc_ich_info *info; + struct mfd_cell *cell = &lpc_ich_cells[LPC_WDT]; + + pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + info = &lpc_chipset_info[priv->chipset]; + + pdata->version = info->iTCO_version; + strlcpy(pdata->name, info->name, sizeof(pdata->name)); + + cell->platform_data = pdata; + cell->pdata_size = sizeof(*pdata); + return 0; +} + +static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + struct mfd_cell *cell = &lpc_ich_cells[LPC_GPIO]; cell->platform_data = &lpc_chipset_info[priv->chipset]; cell->pdata_size = sizeof(struct lpc_ich_info); @@ -933,7 +956,7 @@ gpe0_done: lpc_chipset_info[priv->chipset].use_gpio = ret; lpc_ich_enable_gpio_space(dev); - lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_GPIO]); + lpc_ich_finalize_gpio_cell(dev); ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, &lpc_ich_cells[LPC_GPIO], 1, NULL, 0, NULL); @@ -1007,7 +1030,10 @@ static int lpc_ich_init_wdt(struct pci_dev *dev) res->end = base_addr + ACPIBASE_PMC_END; } - lpc_ich_finalize_cell(dev, &lpc_ich_cells[LPC_WDT]); + ret = lpc_ich_finalize_wdt_cell(dev); + if (ret) + goto wdt_done; + ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, &lpc_ich_cells[LPC_WDT], 1, NULL, 0, NULL); diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index d734763dab69..fbd1cc7d5de3 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include /* * IPC registers @@ -460,9 +460,9 @@ static struct resource tco_res[] = { }, }; -static struct lpc_ich_info tco_info = { +static struct itco_wdt_platform_data tco_info = { .name = "Apollo Lake SoC", - .iTCO_version = 3, + .version = 3, }; static int ipc_create_punit_device(void) @@ -539,8 +539,7 @@ static int ipc_create_tco_device(void) goto err; } - ret = platform_device_add_data(pdev, &tco_info, - sizeof(struct lpc_ich_info)); + ret = platform_device_add_data(pdev, &tco_info, sizeof(tco_info)); if (ret) { dev_err(ipcdev.dev, "Failed to add tco platform data\n"); goto err; diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 3c3fd417ddeb..a94401b2deca 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -66,8 +66,7 @@ #include /* For spin_lock/spin_unlock/... */ #include /* For copy_to_user/put_user/... */ #include /* For inb/outb/... */ -#include -#include +#include #include "iTCO_vendor.h" @@ -418,9 +417,9 @@ static int iTCO_wdt_probe(struct platform_device *dev) { int ret = -ENODEV; unsigned long val32; - struct lpc_ich_info *ich_info = dev_get_platdata(&dev->dev); + struct itco_wdt_platform_data *pdata = dev_get_platdata(&dev->dev); - if (!ich_info) + if (!pdata) goto out; spin_lock_init(&iTCO_wdt_private.io_lock); @@ -435,7 +434,7 @@ static int iTCO_wdt_probe(struct platform_device *dev) if (!iTCO_wdt_private.smi_res) goto out; - iTCO_wdt_private.iTCO_version = ich_info->iTCO_version; + iTCO_wdt_private.iTCO_version = pdata->version; iTCO_wdt_private.dev = dev; iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent); @@ -501,7 +500,7 @@ static int iTCO_wdt_probe(struct platform_device *dev) } pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n", - ich_info->name, ich_info->iTCO_version, (u64)TCOBASE); + pdata->name, pdata->version, (u64)TCOBASE); /* Clear out the (probably old) status */ if (iTCO_wdt_private.iTCO_version == 3) { diff --git a/include/linux/mfd/lpc_ich.h b/include/linux/mfd/lpc_ich.h index 8feac782fa83..2b300b44f994 100644 --- a/include/linux/mfd/lpc_ich.h +++ b/include/linux/mfd/lpc_ich.h @@ -20,12 +20,6 @@ #ifndef LPC_ICH_H #define LPC_ICH_H -/* Watchdog resources */ -#define ICH_RES_IO_TCO 0 -#define ICH_RES_IO_SMI 1 -#define ICH_RES_MEM_OFF 2 -#define ICH_RES_MEM_GCS_PMC 0 - /* GPIO resources */ #define ICH_RES_GPIO 0 #define ICH_RES_GPE0 1 diff --git a/include/linux/platform_data/itco_wdt.h b/include/linux/platform_data/itco_wdt.h new file mode 100644 index 000000000000..f16542c77ff7 --- /dev/null +++ b/include/linux/platform_data/itco_wdt.h @@ -0,0 +1,19 @@ +/* + * Platform data for the Intel TCO Watchdog + */ + +#ifndef _ITCO_WDT_H_ +#define _ITCO_WDT_H_ + +/* Watchdog resources */ +#define ICH_RES_IO_TCO 0 +#define ICH_RES_IO_SMI 1 +#define ICH_RES_MEM_OFF 2 +#define ICH_RES_MEM_GCS_PMC 0 + +struct itco_wdt_platform_data { + char name[32]; + unsigned int version; +}; + +#endif /* _ITCO_WDT_H_ */ -- cgit v1.2.3 From 16478b61f0d88a08163b92af27f0e77f471576ce Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 11 Aug 2015 17:17:18 +0200 Subject: ARM/fb: ep93xx: switch framebuffer to use modedb only All the EP93xx boards exclusively use modedb to look up video modes from the command line. Root out the parametrization of custom video modes from the platform data and board files and simplify the driver. Cc: Jean-Christophe Plagniol-Villard Reviewed-by: H Hartley Sweeten Acked-by: Tomi Valkeinen Signed-off-by: Linus Walleij Signed-off-by: Olof Johansson --- arch/arm/mach-ep93xx/edb93xx.c | 2 -- arch/arm/mach-ep93xx/simone.c | 2 -- arch/arm/mach-ep93xx/snappercl15.c | 2 -- arch/arm/mach-ep93xx/vision_ep9307.c | 2 -- drivers/video/fbdev/ep93xx-fb.c | 30 ++++-------------------------- include/linux/platform_data/video-ep93xx.h | 8 -------- 6 files changed, 4 insertions(+), 42 deletions(-) (limited to 'include/linux/platform_data') diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index 27b14ae92c7e..ad92d9f7e4df 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -205,8 +205,6 @@ static void __init edb93xx_register_pwm(void) * EDB93xx framebuffer *************************************************************************/ static struct ep93xxfb_mach_info __initdata edb93xxfb_info = { - .num_modes = EP93XXFB_USE_MODEDB, - .bpp = 16, .flags = 0, }; diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index d0938a219443..7bb540c421ee 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c @@ -40,8 +40,6 @@ static struct ep93xx_eth_data __initdata simone_eth_data = { }; static struct ep93xxfb_mach_info __initdata simone_fb_info = { - .num_modes = EP93XXFB_USE_MODEDB, - .bpp = 16, .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, }; diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index aa86f86638dd..c4904264256a 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -144,8 +144,6 @@ static struct i2c_board_info __initdata snappercl15_i2c_data[] = { }; static struct ep93xxfb_mach_info __initdata snappercl15_fb_info = { - .num_modes = EP93XXFB_USE_MODEDB, - .bpp = 16, }; static struct platform_device snappercl15_audio_device = { diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c index ff22a6a6e2bf..5cced5988498 100644 --- a/arch/arm/mach-ep93xx/vision_ep9307.c +++ b/arch/arm/mach-ep93xx/vision_ep9307.c @@ -106,8 +106,6 @@ static void vision_lcd_blank(int blank_mode, struct fb_info *info) } static struct ep93xxfb_mach_info ep93xxfb_info __initdata = { - .num_modes = EP93XXFB_USE_MODEDB, - .bpp = 16, .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, .setup = vision_lcd_setup, .teardown = vision_lcd_teardown, diff --git a/drivers/video/fbdev/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c index 7ec251cc9c03..5b1081030cbb 100644 --- a/drivers/video/fbdev/ep93xx-fb.c +++ b/drivers/video/fbdev/ep93xx-fb.c @@ -419,36 +419,15 @@ static struct fb_ops ep93xxfb_ops = { .fb_mmap = ep93xxfb_mmap, }; -static int ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info) -{ - int i, fb_size = 0; - - if (mach_info->num_modes == EP93XXFB_USE_MODEDB) { - fb_size = EP93XXFB_MAX_XRES * EP93XXFB_MAX_YRES * - mach_info->bpp / 8; - } else { - for (i = 0; i < mach_info->num_modes; i++) { - const struct fb_videomode *mode; - int size; - - mode = &mach_info->modes[i]; - size = mode->xres * mode->yres * mach_info->bpp / 8; - if (size > fb_size) - fb_size = size; - } - } - - return fb_size; -} - static int ep93xxfb_alloc_videomem(struct fb_info *info) { - struct ep93xx_fbi *fbi = info->par; char __iomem *virt_addr; dma_addr_t phys_addr; unsigned int fb_size; - fb_size = ep93xxfb_calc_fbsize(fbi->mach_info); + /* Maximum 16bpp -> used memory is maximum x*y*2 bytes */ + fb_size = EP93XXFB_MAX_XRES * EP93XXFB_MAX_YRES * 2; + virt_addr = dma_alloc_writecombine(info->dev, fb_size, &phys_addr, GFP_KERNEL); if (!virt_addr) @@ -550,8 +529,7 @@ static int ep93xxfb_probe(struct platform_device *pdev) fb_get_options("ep93xx-fb", &video_mode); err = fb_find_mode(&info->var, info, video_mode, - fbi->mach_info->modes, fbi->mach_info->num_modes, - fbi->mach_info->default_mode, fbi->mach_info->bpp); + NULL, 0, NULL, 16); if (err == 0) { dev_err(info->dev, "No suitable video mode found\n"); err = -EINVAL; diff --git a/include/linux/platform_data/video-ep93xx.h b/include/linux/platform_data/video-ep93xx.h index 92fc2b2232e7..699ac4109366 100644 --- a/include/linux/platform_data/video-ep93xx.h +++ b/include/linux/platform_data/video-ep93xx.h @@ -2,11 +2,8 @@ #define __VIDEO_EP93XX_H struct platform_device; -struct fb_videomode; struct fb_info; -#define EP93XXFB_USE_MODEDB 0 - /* VideoAttributes flags */ #define EP93XXFB_STATE_MACHINE_ENABLE (1 << 0) #define EP93XXFB_PIXEL_CLOCK_ENABLE (1 << 1) @@ -38,12 +35,7 @@ struct fb_info; EP93XXFB_PIXEL_DATA_ENABLE) struct ep93xxfb_mach_info { - unsigned int num_modes; - const struct fb_videomode *modes; - const struct fb_videomode *default_mode; - int bpp; unsigned int flags; - int (*setup)(struct platform_device *pdev); void (*teardown)(struct platform_device *pdev); void (*blank)(int blank_mode, struct fb_info *info); -- cgit v1.2.3 From b4f194706dd98d6de21c97eeb888a75abbf75174 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 10 Aug 2015 16:23:09 +0200 Subject: USB: host: ohci-at91: move at91_usbh_data definition in c file Move struct at91_usbh_data back in ohci-at91.c as this is the only user left after switching all at91 platforms to DT only. Signed-off-by: Alexandre Belloni Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-at91.c | 11 +++++++++++ include/linux/platform_data/atmel.h | 12 ------------ 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 15df00cceed9..72dc4f9e2a0f 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -36,6 +36,17 @@ #define hcd_to_ohci_at91_priv(h) \ ((struct ohci_at91_priv *)hcd_to_ohci(h)->priv) +#define AT91_MAX_USBH_PORTS 3 +struct at91_usbh_data { + int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */ + int overcurrent_pin[AT91_MAX_USBH_PORTS]; + u8 ports; /* number of ports on root hub */ + u8 overcurrent_supported; + u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS]; + u8 overcurrent_status[AT91_MAX_USBH_PORTS]; + u8 overcurrent_changed[AT91_MAX_USBH_PORTS]; +}; + struct ohci_at91_priv { struct clk *iclk; struct clk *fclk; diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h index 4b452c6a2f7b..527a85c61924 100644 --- a/include/linux/platform_data/atmel.h +++ b/include/linux/platform_data/atmel.h @@ -46,18 +46,6 @@ struct at91_cf_data { #define AT91_IDE_SWAP_A0_A2 0x02 }; - /* USB Host */ -#define AT91_MAX_USBH_PORTS 3 -struct at91_usbh_data { - int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */ - int overcurrent_pin[AT91_MAX_USBH_PORTS]; - u8 ports; /* number of ports on root hub */ - u8 overcurrent_supported; - u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS]; - u8 overcurrent_status[AT91_MAX_USBH_PORTS]; - u8 overcurrent_changed[AT91_MAX_USBH_PORTS]; -}; - /* NAND / SmartMedia */ struct atmel_nand_data { int enable_pin; /* chip enable */ -- cgit v1.2.3 From 76b733d15874128ee2d0365b4cbe7d51decd8d37 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Fri, 14 Aug 2015 22:33:30 +0200 Subject: nfc: st-nci: Remove duplicate file platform_data/st_nci.h commit "nfc: st-nci: Rename st21nfcb to st-nci" adds include/linux/platform_data/st_nci.h duplicated with include/linux/platform_data/st-nci.h. Only drivers/nfc/st-nci/i2c.c uses platform_data/st_nci.h. Cc: stable@vger.kernel.org Reported-by: Hauke Mehrtens Signed-off-by: Christophe Ricard Signed-off-by: Samuel Ortiz --- drivers/nfc/st-nci/i2c.c | 2 +- include/linux/platform_data/st_nci.h | 29 ----------------------------- 2 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 include/linux/platform_data/st_nci.h (limited to 'include/linux/platform_data') diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c index 06175ce769bb..b2a467c2d668 100644 --- a/drivers/nfc/st-nci/i2c.c +++ b/drivers/nfc/st-nci/i2c.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include "ndlc.h" diff --git a/include/linux/platform_data/st_nci.h b/include/linux/platform_data/st_nci.h deleted file mode 100644 index d9d400a297bd..000000000000 --- a/include/linux/platform_data/st_nci.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Driver include for ST NCI NFC chip family. - * - * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef _ST_NCI_H_ -#define _ST_NCI_H_ - -#define ST_NCI_DRIVER_NAME "st_nci" - -struct st_nci_nfc_platform_data { - unsigned int gpio_reset; - unsigned int irq_polarity; -}; - -#endif /* _ST_NCI_H_ */ -- cgit v1.2.3 From 44f636da4e71e0c73d6e29d0319a8954ce3f247a Mon Sep 17 00:00:00 2001 From: Leilk Liu Date: Thu, 20 Aug 2015 17:19:06 +0800 Subject: spi: mediatek: fix spi incorrect endian usage TX_ENDIAN/RX_ENDIAN bits define whether to reverse the endian order of the data DMA from/to memory. The endian order should keep the same with cpu endian. Signed-off-by: Leilk Liu Signed-off-by: Mark Brown --- drivers/spi/spi-mt65xx.c | 38 ++++++++++++++------------------ include/linux/platform_data/spi-mt65xx.h | 2 -- 2 files changed, 16 insertions(+), 24 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 546d70cc1e21..2eda2d1782f3 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -122,8 +122,6 @@ static const struct mtk_spi_compatible mt8173_compat = { static const struct mtk_chip_config mtk_default_chip_info = { .rx_mlsb = 1, .tx_mlsb = 1, - .tx_endian = 0, - .rx_endian = 0, }; static const struct of_device_id mtk_spi_of_match[] = { @@ -161,9 +159,13 @@ static void mtk_spi_config(struct mtk_spi *mdata, reg_val |= (chip_config->rx_mlsb << SPI_CMD_RXMSBF_OFFSET); /* set the tx/rx endian */ - reg_val &= ~(SPI_CMD_TX_ENDIAN | SPI_CMD_RX_ENDIAN); - reg_val |= (chip_config->tx_endian << SPI_CMD_TX_ENDIAN_OFFSET); - reg_val |= (chip_config->rx_endian << SPI_CMD_RX_ENDIAN_OFFSET); +#ifdef __LITTLE_ENDIAN + reg_val &= ~SPI_CMD_TX_ENDIAN; + reg_val &= ~SPI_CMD_RX_ENDIAN; +#else + reg_val |= SPI_CMD_TX_ENDIAN; + reg_val |= SPI_CMD_RX_ENDIAN; +#endif /* set finish and pause interrupt always enable */ reg_val |= SPI_CMD_FINISH_IE | SPI_CMD_PAUSE_EN; @@ -352,7 +354,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { - int cnt, i; + int cnt; struct mtk_spi *mdata = spi_master_get_devdata(master); mdata->cur_transfer = xfer; @@ -364,10 +366,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, cnt = xfer->len / 4 + 1; else cnt = xfer->len / 4; - - for (i = 0; i < cnt; i++) - writel(*((u32 *)xfer->tx_buf + i), - mdata->base + SPI_TX_DATA_REG); + iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt); mtk_spi_enable_transfer(master); @@ -437,7 +436,7 @@ static bool mtk_spi_can_dma(struct spi_master *master, static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) { - u32 cmd, reg_val, i; + u32 cmd, reg_val, cnt; struct spi_master *master = dev_id; struct mtk_spi *mdata = spi_master_get_devdata(master); struct spi_transfer *trans = mdata->cur_transfer; @@ -449,18 +448,13 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) mdata->state = MTK_SPI_IDLE; if (!master->can_dma(master, master->cur_msg->spi, trans)) { - /* xfer len is not N*4 bytes every time in a transfer, - * but SPI_RX_DATA_REG must reads 4 bytes once, - * so rx buffer byte by byte. - */ if (trans->rx_buf) { - for (i = 0; i < mdata->xfer_len; i++) { - if (i % 4 == 0) - reg_val = - readl(mdata->base + SPI_RX_DATA_REG); - *((u8 *)(trans->rx_buf + i)) = - (reg_val >> ((i % 4) * 8)) & 0xff; - } + if (mdata->xfer_len % 4) + cnt = mdata->xfer_len / 4 + 1; + else + cnt = mdata->xfer_len / 4; + ioread32_rep(mdata->base + SPI_RX_DATA_REG, + trans->rx_buf, cnt); } spi_finalize_current_transfer(master); return IRQ_HANDLED; diff --git a/include/linux/platform_data/spi-mt65xx.h b/include/linux/platform_data/spi-mt65xx.h index 751225569d27..54b04483976c 100644 --- a/include/linux/platform_data/spi-mt65xx.h +++ b/include/linux/platform_data/spi-mt65xx.h @@ -16,7 +16,5 @@ struct mtk_chip_config { u32 tx_mlsb; u32 rx_mlsb; - u32 tx_endian; - u32 rx_endian; }; #endif -- cgit v1.2.3 From b3fdd32799d834e2626fae087906e886037350c6 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 17 Aug 2015 11:53:48 -0700 Subject: i2c: mux: Add register-based mux i2c-mux-reg Based on i2c-mux-gpio driver, similarly the register-based mux switch from one bus to another by setting a single register. The register can be on PCIe bus, local bus, or any memory-mapped address. The endianness of such register can be specified in device tree if used, or in platform data. Signed-off-by: York Sun Acked-by: Alexander Sverdlin Signed-off-by: Wolfram Sang --- .../devicetree/bindings/i2c/i2c-mux-reg.txt | 74 ++++++ drivers/i2c/muxes/Kconfig | 11 + drivers/i2c/muxes/Makefile | 1 + drivers/i2c/muxes/i2c-mux-reg.c | 294 +++++++++++++++++++++ include/linux/platform_data/i2c-mux-reg.h | 44 +++ 5 files changed, 424 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt create mode 100644 drivers/i2c/muxes/i2c-mux-reg.c create mode 100644 include/linux/platform_data/i2c-mux-reg.h (limited to 'include/linux/platform_data') diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt new file mode 100644 index 000000000000..688783fbe696 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt @@ -0,0 +1,74 @@ +Register-based I2C Bus Mux + +This binding describes an I2C bus multiplexer that uses a single register +to route the I2C signals. + +Required properties: +- compatible: i2c-mux-reg +- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side + port is connected to. +* Standard I2C mux properties. See mux.txt in this directory. +* I2C child bus nodes. See mux.txt in this directory. + +Optional properties: +- reg: this pair of specifies the register to control the mux. + The depends on its parent node. It can be any memory-mapped + address. The size must be either 1, 2, or 4 bytes. If reg is omitted, the + resource of this device will be used. +- little-endian: The existence indicates the register is in little endian. +- big-endian: The existence indicates the register is in big endian. + If both little-endian and big-endian are omitted, the endianness of the + CPU will be used. +- write-only: The existence indicates the register is write-only. +- idle-state: value to set the muxer to when idle. When no value is + given, it defaults to the last value used. + +Whenever an access is made to a device on a child bus, the value set +in the revelant node's reg property will be output to the register. + +If an idle state is defined, using the idle-state (optional) property, +whenever an access is not being made to a device on a child bus, the +register will be set according to the idle value. + +If an idle state is not defined, the most recently used value will be +left programmed into the register. + +Example of a mux on PCIe card, the host is a powerpc SoC (big endian): + + i2c-mux { + /* the depends on the address translation + * of the parent device. If omitted, device resource + * will be used instead. The size is to determine + * whether iowrite32, iowrite16, or iowrite8 will be used. + */ + reg = <0x6028 0x4>; + little-endian; /* little endian register on PCIe */ + compatible = "i2c-mux-reg"; + #address-cells = <1>; + #size-cells = <0>; + i2c-parent = <&i2c1>; + i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + si5338: clock-generator@70 { + compatible = "silabs,si5338"; + reg = <0x70>; + /* other stuff */ + }; + }; + + i2c@1 { + /* data is written using iowrite32 */ + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + si5338: clock-generator@70 { + compatible = "silabs,si5338"; + reg = <0x70>; + /* other stuff */ + }; + }; + }; diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index fdd0769c84a3..f06b0e24673b 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -61,4 +61,15 @@ config I2C_MUX_PINCTRL This driver can also be built as a module. If so, the module will be called pinctrl-i2cmux. +config I2C_MUX_REG + tristate "Register-based I2C multiplexer" + help + If you say yes to this option, support will be included for a + register based I2C multiplexer. This driver provides access to + I2C busses connected through a MUX, which is controlled + by a single register. + + This driver can also be built as a module. If so, the module + will be called i2c-mux-reg. + endmenu diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile index 465778b5d5dc..e89799b76a92 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o obj-$(CONFIG_I2C_MUX_PINCTRL) += i2c-mux-pinctrl.o +obj-$(CONFIG_I2C_MUX_REG) += i2c-mux-reg.o ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c new file mode 100644 index 000000000000..86d41d36a783 --- /dev/null +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -0,0 +1,294 @@ +/* + * I2C multiplexer using a single register + * + * Copyright 2015 Freescale Semiconductor + * York Sun + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct regmux { + struct i2c_adapter *parent; + struct i2c_adapter **adap; /* child busses */ + struct i2c_mux_reg_platform_data data; +}; + +static int i2c_mux_reg_set(const struct regmux *mux, unsigned int chan_id) +{ + if (!mux->data.reg) + return -EINVAL; + + switch (mux->data.reg_size) { + case 4: + if (mux->data.little_endian) { + iowrite32(chan_id, mux->data.reg); + if (!mux->data.write_only) + ioread32(mux->data.reg); + } else { + iowrite32be(chan_id, mux->data.reg); + if (!mux->data.write_only) + ioread32(mux->data.reg); + } + break; + case 2: + if (mux->data.little_endian) { + iowrite16(chan_id, mux->data.reg); + if (!mux->data.write_only) + ioread16(mux->data.reg); + } else { + iowrite16be(chan_id, mux->data.reg); + if (!mux->data.write_only) + ioread16be(mux->data.reg); + } + break; + case 1: + iowrite8(chan_id, mux->data.reg); + if (!mux->data.write_only) + ioread8(mux->data.reg); + break; + default: + pr_err("Invalid register size\n"); + return -EINVAL; + } + + return 0; +} + +static int i2c_mux_reg_select(struct i2c_adapter *adap, void *data, + unsigned int chan) +{ + struct regmux *mux = data; + + return i2c_mux_reg_set(mux, chan); +} + +static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data, + unsigned int chan) +{ + struct regmux *mux = data; + + if (mux->data.idle_in_use) + return i2c_mux_reg_set(mux, mux->data.idle); + + return 0; +} + +#ifdef CONFIG_OF +static int i2c_mux_reg_probe_dt(struct regmux *mux, + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *adapter_np, *child; + struct i2c_adapter *adapter; + struct resource res; + unsigned *values; + int i = 0; + + if (!np) + return -ENODEV; + + adapter_np = of_parse_phandle(np, "i2c-parent", 0); + if (!adapter_np) { + dev_err(&pdev->dev, "Cannot parse i2c-parent\n"); + return -ENODEV; + } + adapter = of_find_i2c_adapter_by_node(adapter_np); + if (!adapter) + return -EPROBE_DEFER; + + mux->parent = adapter; + mux->data.parent = i2c_adapter_id(adapter); + put_device(&adapter->dev); + + mux->data.n_values = of_get_child_count(np); + if (of_find_property(np, "little-endian", NULL)) { + mux->data.little_endian = true; + } else if (of_find_property(np, "big-endian", NULL)) { + mux->data.little_endian = false; + } else { +#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \ + defined(__LITTLE_ENDIAN) + mux->data.little_endian = true; +#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : \ + defined(__BIG_ENDIAN) + mux->data.little_endian = false; +#else +#error Endianness not defined? +#endif + } + if (of_find_property(np, "write-only", NULL)) + mux->data.write_only = true; + else + mux->data.write_only = false; + + values = devm_kzalloc(&pdev->dev, + sizeof(*mux->data.values) * mux->data.n_values, + GFP_KERNEL); + if (!values) { + dev_err(&pdev->dev, "Cannot allocate values array"); + return -ENOMEM; + } + + for_each_child_of_node(np, child) { + of_property_read_u32(child, "reg", values + i); + i++; + } + mux->data.values = values; + + if (!of_property_read_u32(np, "idle-state", &mux->data.idle)) + mux->data.idle_in_use = true; + + /* map address from "reg" if exists */ + if (of_address_to_resource(np, 0, &res)) { + mux->data.reg_size = resource_size(&res); + if (mux->data.reg_size > 4) { + dev_err(&pdev->dev, "Invalid address size\n"); + return -EINVAL; + } + mux->data.reg = devm_ioremap_resource(&pdev->dev, &res); + if (IS_ERR(mux->data.reg)) + return PTR_ERR(mux->data.reg); + } + + return 0; +} +#else +static int i2c_mux_reg_probe_dt(struct gpiomux *mux, + struct platform_device *pdev) +{ + return 0; +} +#endif + +static int i2c_mux_reg_probe(struct platform_device *pdev) +{ + struct regmux *mux; + struct i2c_adapter *parent; + struct resource *res; + int (*deselect)(struct i2c_adapter *, void *, u32); + unsigned int class; + int i, ret, nr; + + mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); + if (!mux) + return -ENOMEM; + + platform_set_drvdata(pdev, mux); + + if (dev_get_platdata(&pdev->dev)) { + memcpy(&mux->data, dev_get_platdata(&pdev->dev), + sizeof(mux->data)); + + parent = i2c_get_adapter(mux->data.parent); + if (!parent) + return -EPROBE_DEFER; + + mux->parent = parent; + } else { + ret = i2c_mux_reg_probe_dt(mux, pdev); + if (ret < 0) { + dev_err(&pdev->dev, "Error parsing device tree"); + return ret; + } + } + + if (!mux->data.reg) { + dev_info(&pdev->dev, + "Register not set, using platform resource\n"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mux->data.reg_size = resource_size(res); + if (mux->data.reg_size > 4) { + dev_err(&pdev->dev, "Invalid resource size\n"); + return -EINVAL; + } + mux->data.reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mux->data.reg)) + return PTR_ERR(mux->data.reg); + } + + mux->adap = devm_kzalloc(&pdev->dev, + sizeof(*mux->adap) * mux->data.n_values, + GFP_KERNEL); + if (!mux->adap) { + dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure"); + return -ENOMEM; + } + + if (mux->data.idle_in_use) + deselect = i2c_mux_reg_deselect; + else + deselect = NULL; + + for (i = 0; i < mux->data.n_values; i++) { + nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0; + class = mux->data.classes ? mux->data.classes[i] : 0; + + mux->adap[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, mux, + nr, mux->data.values[i], + class, i2c_mux_reg_select, + deselect); + if (!mux->adap[i]) { + ret = -ENODEV; + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + dev_dbg(&pdev->dev, "%d port mux on %s adapter\n", + mux->data.n_values, mux->parent->name); + + return 0; + +add_adapter_failed: + for (; i > 0; i--) + i2c_del_mux_adapter(mux->adap[i - 1]); + + return ret; +} + +static int i2c_mux_reg_remove(struct platform_device *pdev) +{ + struct regmux *mux = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < mux->data.n_values; i++) + i2c_del_mux_adapter(mux->adap[i]); + + i2c_put_adapter(mux->parent); + + return 0; +} + +static const struct of_device_id i2c_mux_reg_of_match[] = { + { .compatible = "i2c-mux-reg", }, + {}, +}; +MODULE_DEVICE_TABLE(of, i2c_mux_reg_of_match); + +static struct platform_driver i2c_mux_reg_driver = { + .probe = i2c_mux_reg_probe, + .remove = i2c_mux_reg_remove, + .driver = { + .name = "i2c-mux-reg", + }, +}; + +module_platform_driver(i2c_mux_reg_driver); + +MODULE_DESCRIPTION("Register-based I2C multiplexer driver"); +MODULE_AUTHOR("York Sun "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:i2c-mux-reg"); diff --git a/include/linux/platform_data/i2c-mux-reg.h b/include/linux/platform_data/i2c-mux-reg.h new file mode 100644 index 000000000000..c68712aadf43 --- /dev/null +++ b/include/linux/platform_data/i2c-mux-reg.h @@ -0,0 +1,44 @@ +/* + * I2C multiplexer using a single register + * + * Copyright 2015 Freescale Semiconductor + * York Sun + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __LINUX_PLATFORM_DATA_I2C_MUX_REG_H +#define __LINUX_PLATFORM_DATA_I2C_MUX_REG_H + +/** + * struct i2c_mux_reg_platform_data - Platform-dependent data for i2c-mux-reg + * @parent: Parent I2C bus adapter number + * @base_nr: Base I2C bus number to number adapters from or zero for dynamic + * @values: Array of value for each channel + * @n_values: Number of multiplexer channels + * @little_endian: Indicating if the register is in little endian + * @write_only: Reading the register is not allowed by hardware + * @classes: Optional I2C auto-detection classes + * @idle: Value to write to mux when idle + * @idle_in_use: indicate if idle value is in use + * @reg: Virtual address of the register to switch channel + * @reg_size: register size in bytes + */ +struct i2c_mux_reg_platform_data { + int parent; + int base_nr; + const unsigned int *values; + int n_values; + bool little_endian; + bool write_only; + const unsigned int *classes; + u32 idle; + bool idle_in_use; + void __iomem *reg; + resource_size_t reg_size; +}; + +#endif /* __LINUX_PLATFORM_DATA_I2C_MUX_REG_H */ -- cgit v1.2.3 From 0f350f063eb62212a701a512f74e63ae4714441c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 30 Jul 2015 15:19:12 +0200 Subject: clk: ux500: delete the non-DT U8500 clock implementation This code is unused and not coming back. Let's kill it off. Cc: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/ux500/Makefile | 1 - drivers/clk/ux500/u8500_clk.c | 525 -------------------------------- include/linux/platform_data/clk-ux500.h | 2 - 3 files changed, 528 deletions(-) delete mode 100644 drivers/clk/ux500/u8500_clk.c (limited to 'include/linux/platform_data') diff --git a/drivers/clk/ux500/Makefile b/drivers/clk/ux500/Makefile index 521483f0ba33..f3baef29859c 100644 --- a/drivers/clk/ux500/Makefile +++ b/drivers/clk/ux500/Makefile @@ -9,7 +9,6 @@ obj-y += clk-sysctrl.o # Clock definitions obj-y += u8500_of_clk.o -obj-y += u8500_clk.o obj-y += u9540_clk.o obj-y += u8540_clk.o diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c deleted file mode 100644 index 1c7b639d9222..000000000000 --- a/drivers/clk/ux500/u8500_clk.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Clock definitions for u8500 platform. - * - * Copyright (C) 2012 ST-Ericsson SA - * Author: Ulf Hansson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#include -#include -#include -#include -#include "clk.h" - -void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, - u32 clkrst5_base, u32 clkrst6_base) -{ - struct prcmu_fw_version *fw_version; - const char *sgaclk_parent = NULL; - struct clk *clk; - - /* Clock sources */ - clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0, - CLK_IS_ROOT|CLK_IGNORE_UNUSED); - clk_register_clkdev(clk, "soc0_pll", NULL); - - clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1, - CLK_IS_ROOT|CLK_IGNORE_UNUSED); - clk_register_clkdev(clk, "soc1_pll", NULL); - - clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR, - CLK_IS_ROOT|CLK_IGNORE_UNUSED); - clk_register_clkdev(clk, "ddr_pll", NULL); - - /* FIXME: Add sys, ulp and int clocks here. */ - - clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL", - CLK_IS_ROOT|CLK_IGNORE_UNUSED, - 32768); - clk_register_clkdev(clk, "clk32k", NULL); - clk_register_clkdev(clk, "apb_pclk", "rtc-pl031"); - - /* PRCMU clocks */ - fw_version = prcmu_get_fw_version(); - if (fw_version != NULL) { - switch (fw_version->project) { - case PRCMU_FW_PROJECT_U8500_C2: - case PRCMU_FW_PROJECT_U8520: - case PRCMU_FW_PROJECT_U8420: - sgaclk_parent = "soc0_pll"; - break; - default: - break; - } - } - - if (sgaclk_parent) - clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent, - PRCMU_SGACLK, 0); - else - clk = clk_reg_prcmu_gate("sgclk", NULL, - PRCMU_SGACLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "mali"); - - clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "UART"); - - clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "MSP02"); - - clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "MSP1"); - - clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "I2C"); - - clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "slim"); - - clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH1"); - - clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH2"); - - clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH3"); - - clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH5"); - - clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH6"); - - clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "PERIPH7"); - - clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "lcd"); - clk_register_clkdev(clk, "lcd", "mcde"); - - clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "bml"); - - clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - - clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - - clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "hdmi"); - clk_register_clkdev(clk, "hdmi", "mcde"); - - clk = clk_reg_prcmu_scalable("apeatclk", NULL, PRCMU_APEATCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "apeat"); - - clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "apetrace"); - - clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "mcde"); - clk_register_clkdev(clk, "mcde", "mcde"); - clk_register_clkdev(clk, "dsisys", "dsilink.0"); - clk_register_clkdev(clk, "dsisys", "dsilink.1"); - clk_register_clkdev(clk, "dsisys", "dsilink.2"); - - clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK, - CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "ipi2"); - - clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK, - CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "dsialt"); - - clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "dma40.0"); - - clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "b2r2"); - clk_register_clkdev(clk, NULL, "b2r2_core"); - clk_register_clkdev(clk, NULL, "U8500-B2R2.0"); - - clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "tv"); - clk_register_clkdev(clk, "tv", "mcde"); - - clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "SSP"); - - clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "rngclk"); - - clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "uicc"); - - clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT); - clk_register_clkdev(clk, NULL, "mtu0"); - clk_register_clkdev(clk, NULL, "mtu1"); - - clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK, - 100000000, - CLK_IS_ROOT|CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdmmc"); - - clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk", - PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsihs2", "mcde"); - clk_register_clkdev(clk, "dsihs2", "dsilink.2"); - - - clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll", - PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsihs0", "mcde"); - clk_register_clkdev(clk, "dsihs0", "dsilink.0"); - - clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll", - PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsihs1", "mcde"); - clk_register_clkdev(clk, "dsihs1", "dsilink.1"); - - clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk", - PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsilp0", "dsilink.0"); - clk_register_clkdev(clk, "dsilp0", "mcde"); - - clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk", - PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsilp1", "dsilink.1"); - clk_register_clkdev(clk, "dsilp1", "mcde"); - - clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk", - PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE); - clk_register_clkdev(clk, "dsilp2", "dsilink.2"); - clk_register_clkdev(clk, "dsilp2", "mcde"); - - clk = clk_reg_prcmu_scalable_rate("armss", NULL, - PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED); - clk_register_clkdev(clk, "armss", NULL); - - clk = clk_register_fixed_factor(NULL, "smp_twd", "armss", - CLK_IGNORE_UNUSED, 1, 2); - clk_register_clkdev(clk, NULL, "smp_twd"); - - /* - * FIXME: Add special handled PRCMU clocks here: - * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl. - * 2. ab9540_clkout1yuv, see clkout0yuv - */ - - /* PRCC P-clocks */ - clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base, - BIT(0), 0); - clk_register_clkdev(clk, "apb_pclk", "uart0"); - - clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base, - BIT(1), 0); - clk_register_clkdev(clk, "apb_pclk", "uart1"); - - clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base, - BIT(2), 0); - clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1"); - - clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base, - BIT(3), 0); - clk_register_clkdev(clk, "apb_pclk", "msp0"); - clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0"); - - clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base, - BIT(4), 0); - clk_register_clkdev(clk, "apb_pclk", "msp1"); - clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1"); - - clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base, - BIT(5), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi0"); - - clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base, - BIT(6), 0); - clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2"); - - clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base, - BIT(7), 0); - clk_register_clkdev(clk, NULL, "spi3"); - - clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base, - BIT(8), 0); - clk_register_clkdev(clk, "apb_pclk", "slimbus0"); - - clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base, - BIT(9), 0); - clk_register_clkdev(clk, NULL, "gpio.0"); - clk_register_clkdev(clk, NULL, "gpio.1"); - clk_register_clkdev(clk, NULL, "gpioblock0"); - - clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base, - BIT(10), 0); - clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4"); - - clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base, - BIT(11), 0); - clk_register_clkdev(clk, "apb_pclk", "msp3"); - clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3"); - - clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base, - BIT(0), 0); - clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3"); - - clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base, - BIT(1), 0); - clk_register_clkdev(clk, NULL, "spi2"); - - clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base, - BIT(2), 0); - clk_register_clkdev(clk, NULL, "spi1"); - - clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base, - BIT(3), 0); - clk_register_clkdev(clk, NULL, "pwl"); - - clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base, - BIT(4), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi4"); - - clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base, - BIT(5), 0); - clk_register_clkdev(clk, "apb_pclk", "msp2"); - clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2"); - - clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base, - BIT(6), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi1"); - - clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base, - BIT(7), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi3"); - - clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base, - BIT(8), 0); - clk_register_clkdev(clk, NULL, "spi0"); - - clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base, - BIT(9), 0); - clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0"); - - clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base, - BIT(10), 0); - clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0"); - - clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base, - BIT(11), 0); - clk_register_clkdev(clk, NULL, "gpio.6"); - clk_register_clkdev(clk, NULL, "gpio.7"); - clk_register_clkdev(clk, NULL, "gpioblock1"); - - clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base, - BIT(12), 0); - - clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base, - BIT(0), 0); - clk_register_clkdev(clk, "fsmc", NULL); - clk_register_clkdev(clk, NULL, "smsc911x.0"); - - clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base, - BIT(1), 0); - clk_register_clkdev(clk, "apb_pclk", "ssp0"); - - clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base, - BIT(2), 0); - clk_register_clkdev(clk, "apb_pclk", "ssp1"); - - clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base, - BIT(3), 0); - clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0"); - - clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base, - BIT(4), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi2"); - - clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base, - BIT(5), 0); - clk_register_clkdev(clk, "apb_pclk", "ske"); - clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad"); - - clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base, - BIT(6), 0); - clk_register_clkdev(clk, "apb_pclk", "uart2"); - - clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base, - BIT(7), 0); - clk_register_clkdev(clk, "apb_pclk", "sdi5"); - - clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base, - BIT(8), 0); - clk_register_clkdev(clk, NULL, "gpio.2"); - clk_register_clkdev(clk, NULL, "gpio.3"); - clk_register_clkdev(clk, NULL, "gpio.4"); - clk_register_clkdev(clk, NULL, "gpio.5"); - clk_register_clkdev(clk, NULL, "gpioblock2"); - - clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base, - BIT(0), 0); - clk_register_clkdev(clk, "usb", "musb-ux500.0"); - - clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base, - BIT(1), 0); - clk_register_clkdev(clk, NULL, "gpio.8"); - clk_register_clkdev(clk, NULL, "gpioblock3"); - - clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base, - BIT(0), 0); - clk_register_clkdev(clk, "apb_pclk", "rng"); - - clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base, - BIT(1), 0); - clk_register_clkdev(clk, NULL, "cryp0"); - clk_register_clkdev(clk, NULL, "cryp1"); - - clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base, - BIT(2), 0); - clk_register_clkdev(clk, NULL, "hash0"); - - clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base, - BIT(3), 0); - clk_register_clkdev(clk, NULL, "pka"); - - clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base, - BIT(4), 0); - clk_register_clkdev(clk, NULL, "hash1"); - - clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base, - BIT(5), 0); - clk_register_clkdev(clk, NULL, "cfgreg"); - - clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base, - BIT(6), 0); - clk_register_clkdev(clk, "apb_pclk", "mtu0"); - - clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base, - BIT(7), 0); - clk_register_clkdev(clk, "apb_pclk", "mtu1"); - - /* PRCC K-clocks - * - * FIXME: Some drivers requires PERPIH[n| to be automatically enabled - * by enabling just the K-clock, even if it is not a valid parent to - * the K-clock. Until drivers get fixed we might need some kind of - * "parent muxed join". - */ - - /* Periph1 */ - clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk", - clkrst1_base, BIT(0), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "uart0"); - - clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk", - clkrst1_base, BIT(1), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "uart1"); - - clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk", - clkrst1_base, BIT(2), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "nmk-i2c.1"); - - clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk", - clkrst1_base, BIT(3), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "msp0"); - clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0"); - - clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk", - clkrst1_base, BIT(4), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "msp1"); - clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1"); - - clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk", - clkrst1_base, BIT(5), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi0"); - - clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk", - clkrst1_base, BIT(6), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "nmk-i2c.2"); - - clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk", - clkrst1_base, BIT(8), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "slimbus0"); - - clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk", - clkrst1_base, BIT(9), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "nmk-i2c.4"); - - clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk", - clkrst1_base, BIT(10), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "msp3"); - clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3"); - - /* Periph2 */ - clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk", - clkrst2_base, BIT(0), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "nmk-i2c.3"); - - clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk", - clkrst2_base, BIT(2), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi4"); - - clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk", - clkrst2_base, BIT(3), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "msp2"); - clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2"); - - clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk", - clkrst2_base, BIT(4), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi1"); - - clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk", - clkrst2_base, BIT(5), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi3"); - - /* Note that rate is received from parent. */ - clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk", - clkrst2_base, BIT(6), - CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); - clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk", - clkrst2_base, BIT(7), - CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); - - /* Periph3 */ - clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk", - clkrst3_base, BIT(1), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "ssp0"); - - clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk", - clkrst3_base, BIT(2), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "ssp1"); - - clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk", - clkrst3_base, BIT(3), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "nmk-i2c.0"); - - clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk", - clkrst3_base, BIT(4), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi2"); - - clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k", - clkrst3_base, BIT(5), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "ske"); - clk_register_clkdev(clk, NULL, "nmk-ske-keypad"); - - clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk", - clkrst3_base, BIT(6), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "uart2"); - - clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk", - clkrst3_base, BIT(7), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "sdi5"); - - /* Periph6 */ - clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk", - clkrst6_base, BIT(0), CLK_SET_RATE_GATE); - clk_register_clkdev(clk, NULL, "rng"); -} diff --git a/include/linux/platform_data/clk-ux500.h b/include/linux/platform_data/clk-ux500.h index 97baf831e071..0058edb24391 100644 --- a/include/linux/platform_data/clk-ux500.h +++ b/include/linux/platform_data/clk-ux500.h @@ -13,8 +13,6 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, u32 clkrst5_base, u32 clkrst6_base); -void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, - u32 clkrst5_base, u32 clkrst6_base); void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, u32 clkrst5_base, u32 clkrst6_base); void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, -- cgit v1.2.3 From 5dc0fe199b358966021b015c71ca4049d0f42aa6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 30 Jul 2015 15:19:25 +0200 Subject: clk/ARM: move Ux500 PRCC bases to the device tree The base addresses for the Ux500 PRCC controllers are hardcoded, let's move them to the clock node in the device tree and delete the constants. Cc: Ulf Hansson Signed-off-by: Linus Walleij Acked-by: Olof Johansson Acked-by: Michael Turquette Signed-off-by: Stephen Boyd --- arch/arm/boot/dts/ste-dbx5x0.dtsi | 7 ++ arch/arm/mach-ux500/cpu.c | 21 +--- drivers/clk/ux500/u8500_of_clk.c | 163 ++++++++++++++------------ drivers/clk/ux500/u8540_clk.c | 197 +++++++++++++++++++------------- drivers/clk/ux500/u9540_clk.c | 3 +- include/linux/platform_data/clk-ux500.h | 10 +- 6 files changed, 225 insertions(+), 176 deletions(-) (limited to 'include/linux/platform_data') diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index 853684ad7773..a56bf890afaf 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -219,6 +219,13 @@ clocks { compatible = "stericsson,u8500-clks"; + /* + * Registers for the CLKRST block on peripheral + * groups 1, 2, 3, 5, 6, + */ + reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>, + <0x8000f000 0x1000>, <0xa03ff000 0x1000>, + <0xa03cf000 0x1000>; prcmu_clk: prcmu-clock { #clock-cells = <1>; diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index e31d3d61c998..b316e18a76aa 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -72,21 +72,12 @@ void __init ux500_init_irq(void) * Init clocks here so that they are available for system timer * initialization. */ - if (cpu_is_u8500_family()) { - u8500_of_clk_init(U8500_CLKRST1_BASE, - U8500_CLKRST2_BASE, - U8500_CLKRST3_BASE, - U8500_CLKRST5_BASE, - U8500_CLKRST6_BASE); - } else if (cpu_is_u9540()) { - u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE, - U8500_CLKRST3_BASE, U8500_CLKRST5_BASE, - U8500_CLKRST6_BASE); - } else if (cpu_is_u8540()) { - u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE, - U8500_CLKRST3_BASE, U8500_CLKRST5_BASE, - U8500_CLKRST6_BASE); - } + if (cpu_is_u8500_family()) + u8500_clk_init(); + else if (cpu_is_u9540()) + u9540_clk_init(); + else if (cpu_is_u8540()) + u8540_clk_init(); } static const char * __init ux500_get_machine(void) diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c index c3e3b20e4b43..271c09644652 100644 --- a/drivers/clk/ux500/u8500_of_clk.c +++ b/drivers/clk/ux500/u8500_of_clk.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -52,14 +53,25 @@ static const struct of_device_id u8500_clk_of_match[] = { { }, }; -void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, - u32 clkrst5_base, u32 clkrst6_base) +/* CLKRST4 is missing making it hard to index things */ +enum clkrst_index { + CLKRST1_INDEX = 0, + CLKRST2_INDEX, + CLKRST3_INDEX, + CLKRST5_INDEX, + CLKRST6_INDEX, + CLKRST_MAX, +}; + +void u8500_clk_init(void) { struct prcmu_fw_version *fw_version; struct device_node *np = NULL; struct device_node *child = NULL; const char *sgaclk_parent = NULL; struct clk *clk, *rtc_clk, *twd_clk; + u32 bases[CLKRST_MAX]; + int i; if (of_have_populated_dt()) np = of_find_matching_node(NULL, u8500_clk_of_match); @@ -67,6 +79,15 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, pr_err("Either DT or U8500 Clock node not found\n"); return; } + for (i = 0; i < ARRAY_SIZE(bases); i++) { + struct resource r; + + if (of_address_to_resource(np, i, &r)) + /* Not much choice but to continue */ + pr_err("failed to get CLKRST %d base address\n", + i + 1); + bases[i] = r.start; + } /* Clock sources */ clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0, @@ -244,179 +265,179 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, */ /* PRCC P-clocks */ - clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", bases[CLKRST1_INDEX], BIT(0), 0); PRCC_PCLK_STORE(clk, 1, 0); - clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", bases[CLKRST1_INDEX], BIT(1), 0); PRCC_PCLK_STORE(clk, 1, 1); - clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", bases[CLKRST1_INDEX], BIT(2), 0); PRCC_PCLK_STORE(clk, 1, 2); - clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", bases[CLKRST1_INDEX], BIT(3), 0); PRCC_PCLK_STORE(clk, 1, 3); - clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", bases[CLKRST1_INDEX], BIT(4), 0); PRCC_PCLK_STORE(clk, 1, 4); - clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", bases[CLKRST1_INDEX], BIT(5), 0); PRCC_PCLK_STORE(clk, 1, 5); - clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", bases[CLKRST1_INDEX], BIT(6), 0); PRCC_PCLK_STORE(clk, 1, 6); - clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", bases[CLKRST1_INDEX], BIT(7), 0); PRCC_PCLK_STORE(clk, 1, 7); - clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", bases[CLKRST1_INDEX], BIT(8), 0); PRCC_PCLK_STORE(clk, 1, 8); - clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", bases[CLKRST1_INDEX], BIT(9), 0); PRCC_PCLK_STORE(clk, 1, 9); - clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", bases[CLKRST1_INDEX], BIT(10), 0); PRCC_PCLK_STORE(clk, 1, 10); - clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", bases[CLKRST1_INDEX], BIT(11), 0); PRCC_PCLK_STORE(clk, 1, 11); - clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", bases[CLKRST2_INDEX], BIT(0), 0); PRCC_PCLK_STORE(clk, 2, 0); - clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", bases[CLKRST2_INDEX], BIT(1), 0); PRCC_PCLK_STORE(clk, 2, 1); - clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", bases[CLKRST2_INDEX], BIT(2), 0); PRCC_PCLK_STORE(clk, 2, 2); - clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", bases[CLKRST2_INDEX], BIT(3), 0); PRCC_PCLK_STORE(clk, 2, 3); - clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", bases[CLKRST2_INDEX], BIT(4), 0); PRCC_PCLK_STORE(clk, 2, 4); - clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", bases[CLKRST2_INDEX], BIT(5), 0); PRCC_PCLK_STORE(clk, 2, 5); - clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", bases[CLKRST2_INDEX], BIT(6), 0); PRCC_PCLK_STORE(clk, 2, 6); - clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", bases[CLKRST2_INDEX], BIT(7), 0); PRCC_PCLK_STORE(clk, 2, 7); - clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", bases[CLKRST2_INDEX], BIT(8), 0); PRCC_PCLK_STORE(clk, 2, 8); - clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", bases[CLKRST2_INDEX], BIT(9), 0); PRCC_PCLK_STORE(clk, 2, 9); - clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", bases[CLKRST2_INDEX], BIT(10), 0); PRCC_PCLK_STORE(clk, 2, 10); - clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", bases[CLKRST2_INDEX], BIT(11), 0); PRCC_PCLK_STORE(clk, 2, 11); - clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", bases[CLKRST2_INDEX], BIT(12), 0); PRCC_PCLK_STORE(clk, 2, 12); - clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", bases[CLKRST3_INDEX], BIT(0), 0); PRCC_PCLK_STORE(clk, 3, 0); - clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", bases[CLKRST3_INDEX], BIT(1), 0); PRCC_PCLK_STORE(clk, 3, 1); - clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", bases[CLKRST3_INDEX], BIT(2), 0); PRCC_PCLK_STORE(clk, 3, 2); - clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", bases[CLKRST3_INDEX], BIT(3), 0); PRCC_PCLK_STORE(clk, 3, 3); - clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", bases[CLKRST3_INDEX], BIT(4), 0); PRCC_PCLK_STORE(clk, 3, 4); - clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", bases[CLKRST3_INDEX], BIT(5), 0); PRCC_PCLK_STORE(clk, 3, 5); - clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", bases[CLKRST3_INDEX], BIT(6), 0); PRCC_PCLK_STORE(clk, 3, 6); - clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", bases[CLKRST3_INDEX], BIT(7), 0); PRCC_PCLK_STORE(clk, 3, 7); - clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", bases[CLKRST3_INDEX], BIT(8), 0); PRCC_PCLK_STORE(clk, 3, 8); - clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base, + clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", bases[CLKRST5_INDEX], BIT(0), 0); PRCC_PCLK_STORE(clk, 5, 0); - clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base, + clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", bases[CLKRST5_INDEX], BIT(1), 0); PRCC_PCLK_STORE(clk, 5, 1); - clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", bases[CLKRST6_INDEX], BIT(0), 0); PRCC_PCLK_STORE(clk, 6, 0); - clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", bases[CLKRST6_INDEX], BIT(1), 0); PRCC_PCLK_STORE(clk, 6, 1); - clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", bases[CLKRST6_INDEX], BIT(2), 0); PRCC_PCLK_STORE(clk, 6, 2); - clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", bases[CLKRST6_INDEX], BIT(3), 0); PRCC_PCLK_STORE(clk, 6, 3); - clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", bases[CLKRST6_INDEX], BIT(4), 0); PRCC_PCLK_STORE(clk, 6, 4); - clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", bases[CLKRST6_INDEX], BIT(5), 0); PRCC_PCLK_STORE(clk, 6, 5); - clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", bases[CLKRST6_INDEX], BIT(6), 0); PRCC_PCLK_STORE(clk, 6, 6); - clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", bases[CLKRST6_INDEX], BIT(7), 0); PRCC_PCLK_STORE(clk, 6, 7); @@ -430,109 +451,109 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, /* Periph1 */ clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk", - clkrst1_base, BIT(0), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(0), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 0); clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk", - clkrst1_base, BIT(1), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(1), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 1); clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk", - clkrst1_base, BIT(2), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(2), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 2); clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk", - clkrst1_base, BIT(3), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(3), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 3); clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk", - clkrst1_base, BIT(4), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(4), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 4); clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk", - clkrst1_base, BIT(5), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(5), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 5); clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk", - clkrst1_base, BIT(6), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(6), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 6); clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk", - clkrst1_base, BIT(8), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(8), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 8); clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk", - clkrst1_base, BIT(9), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(9), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 9); clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk", - clkrst1_base, BIT(10), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(10), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 1, 10); /* Periph2 */ clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk", - clkrst2_base, BIT(0), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(0), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 2, 0); clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk", - clkrst2_base, BIT(2), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(2), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 2, 2); clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk", - clkrst2_base, BIT(3), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(3), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 2, 3); clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk", - clkrst2_base, BIT(4), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(4), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 2, 4); clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk", - clkrst2_base, BIT(5), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(5), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 2, 5); /* Note that rate is received from parent. */ clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk", - clkrst2_base, BIT(6), + bases[CLKRST2_INDEX], BIT(6), CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); PRCC_KCLK_STORE(clk, 2, 6); clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk", - clkrst2_base, BIT(7), + bases[CLKRST2_INDEX], BIT(7), CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); PRCC_KCLK_STORE(clk, 2, 7); /* Periph3 */ clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk", - clkrst3_base, BIT(1), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(1), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 3, 1); clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk", - clkrst3_base, BIT(2), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(2), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 3, 2); clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk", - clkrst3_base, BIT(3), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(3), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 3, 3); clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk", - clkrst3_base, BIT(4), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(4), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 3, 4); clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k", - clkrst3_base, BIT(5), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(5), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 3, 5); clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk", - clkrst3_base, BIT(6), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(6), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 3, 6); clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk", - clkrst3_base, BIT(7), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(7), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 3, 7); /* Periph6 */ clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk", - clkrst6_base, BIT(0), CLK_SET_RATE_GATE); + bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE); PRCC_KCLK_STORE(clk, 6, 0); for_each_child_of_node(np, child) { diff --git a/drivers/clk/ux500/u8540_clk.c b/drivers/clk/ux500/u8540_clk.c index d0de335ea1e9..d7bcb7a86615 100644 --- a/drivers/clk/ux500/u8540_clk.c +++ b/drivers/clk/ux500/u8540_clk.c @@ -7,16 +7,51 @@ * License terms: GNU General Public License (GPL) version 2 */ +#include +#include #include #include #include #include #include "clk.h" -void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, - u32 clkrst5_base, u32 clkrst6_base) +static const struct of_device_id u8540_clk_of_match[] = { + { .compatible = "stericsson,u8540-clks", }, + { } +}; + +/* CLKRST4 is missing making it hard to index things */ +enum clkrst_index { + CLKRST1_INDEX = 0, + CLKRST2_INDEX, + CLKRST3_INDEX, + CLKRST5_INDEX, + CLKRST6_INDEX, + CLKRST_MAX, +}; + +void u8540_clk_init(void) { struct clk *clk; + struct device_node *np = NULL; + u32 bases[CLKRST_MAX]; + int i; + + if (of_have_populated_dt()) + np = of_find_matching_node(NULL, u8540_clk_of_match); + if (!np) { + pr_err("Either DT or U8540 Clock node not found\n"); + return; + } + for (i = 0; i < ARRAY_SIZE(bases); i++) { + struct resource r; + + if (of_address_to_resource(np, i, &r)) + /* Not much choice but to continue */ + pr_err("failed to get CLKRST %d base address\n", + i + 1); + bases[i] = r.start; + } /* Clock sources. */ /* Fixed ClockGen */ @@ -218,151 +253,151 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, /* PRCC P-clocks */ /* Peripheral 1 : PRCC P-clocks */ - clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", bases[CLKRST1_INDEX], BIT(0), 0); clk_register_clkdev(clk, "apb_pclk", "uart0"); - clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", bases[CLKRST1_INDEX], BIT(1), 0); clk_register_clkdev(clk, "apb_pclk", "uart1"); - clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", bases[CLKRST1_INDEX], BIT(2), 0); clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1"); - clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", bases[CLKRST1_INDEX], BIT(3), 0); clk_register_clkdev(clk, "apb_pclk", "msp0"); clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.0"); - clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", bases[CLKRST1_INDEX], BIT(4), 0); clk_register_clkdev(clk, "apb_pclk", "msp1"); clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.1"); - clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", bases[CLKRST1_INDEX], BIT(5), 0); clk_register_clkdev(clk, "apb_pclk", "sdi0"); - clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", bases[CLKRST1_INDEX], BIT(6), 0); clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2"); - clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", bases[CLKRST1_INDEX], BIT(7), 0); clk_register_clkdev(clk, NULL, "spi3"); - clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", bases[CLKRST1_INDEX], BIT(8), 0); clk_register_clkdev(clk, "apb_pclk", "slimbus0"); - clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", bases[CLKRST1_INDEX], BIT(9), 0); clk_register_clkdev(clk, NULL, "gpio.0"); clk_register_clkdev(clk, NULL, "gpio.1"); clk_register_clkdev(clk, NULL, "gpioblock0"); clk_register_clkdev(clk, "apb_pclk", "ab85xx-codec.0"); - clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", bases[CLKRST1_INDEX], BIT(10), 0); clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4"); - clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base, + clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", bases[CLKRST1_INDEX], BIT(11), 0); clk_register_clkdev(clk, "apb_pclk", "msp3"); clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.3"); /* Peripheral 2 : PRCC P-clocks */ - clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", bases[CLKRST2_INDEX], BIT(0), 0); clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3"); - clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", bases[CLKRST2_INDEX], BIT(1), 0); clk_register_clkdev(clk, NULL, "spi2"); - clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", bases[CLKRST2_INDEX], BIT(2), 0); clk_register_clkdev(clk, NULL, "spi1"); - clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", bases[CLKRST2_INDEX], BIT(3), 0); clk_register_clkdev(clk, NULL, "pwl"); - clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", bases[CLKRST2_INDEX], BIT(4), 0); clk_register_clkdev(clk, "apb_pclk", "sdi4"); - clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", bases[CLKRST2_INDEX], BIT(5), 0); clk_register_clkdev(clk, "apb_pclk", "msp2"); clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.2"); - clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", bases[CLKRST2_INDEX], BIT(6), 0); clk_register_clkdev(clk, "apb_pclk", "sdi1"); - clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", bases[CLKRST2_INDEX], BIT(7), 0); clk_register_clkdev(clk, "apb_pclk", "sdi3"); - clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", bases[CLKRST2_INDEX], BIT(8), 0); clk_register_clkdev(clk, NULL, "spi0"); - clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", bases[CLKRST2_INDEX], BIT(9), 0); clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0"); - clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", bases[CLKRST2_INDEX], BIT(10), 0); clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0"); - clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", bases[CLKRST2_INDEX], BIT(11), 0); clk_register_clkdev(clk, NULL, "gpio.6"); clk_register_clkdev(clk, NULL, "gpio.7"); clk_register_clkdev(clk, NULL, "gpioblock1"); - clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base, + clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", bases[CLKRST2_INDEX], BIT(12), 0); clk_register_clkdev(clk, "msp4-pclk", "ab85xx-codec.0"); /* Peripheral 3 : PRCC P-clocks */ - clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", bases[CLKRST3_INDEX], BIT(0), 0); clk_register_clkdev(clk, NULL, "fsmc"); - clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", bases[CLKRST3_INDEX], BIT(1), 0); clk_register_clkdev(clk, "apb_pclk", "ssp0"); - clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", bases[CLKRST3_INDEX], BIT(2), 0); clk_register_clkdev(clk, "apb_pclk", "ssp1"); - clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", bases[CLKRST3_INDEX], BIT(3), 0); clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0"); - clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", bases[CLKRST3_INDEX], BIT(4), 0); clk_register_clkdev(clk, "apb_pclk", "sdi2"); - clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", bases[CLKRST3_INDEX], BIT(5), 0); clk_register_clkdev(clk, "apb_pclk", "ske"); clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad"); - clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", bases[CLKRST3_INDEX], BIT(6), 0); clk_register_clkdev(clk, "apb_pclk", "uart2"); - clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", bases[CLKRST3_INDEX], BIT(7), 0); clk_register_clkdev(clk, "apb_pclk", "sdi5"); - clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", bases[CLKRST3_INDEX], BIT(8), 0); clk_register_clkdev(clk, NULL, "gpio.2"); clk_register_clkdev(clk, NULL, "gpio.3"); @@ -370,64 +405,64 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, clk_register_clkdev(clk, NULL, "gpio.5"); clk_register_clkdev(clk, NULL, "gpioblock2"); - clk = clk_reg_prcc_pclk("p3_pclk9", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk9", "per3clk", bases[CLKRST3_INDEX], BIT(9), 0); clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.5"); - clk = clk_reg_prcc_pclk("p3_pclk10", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk10", "per3clk", bases[CLKRST3_INDEX], BIT(10), 0); clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.6"); - clk = clk_reg_prcc_pclk("p3_pclk11", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk11", "per3clk", bases[CLKRST3_INDEX], BIT(11), 0); clk_register_clkdev(clk, "apb_pclk", "uart3"); - clk = clk_reg_prcc_pclk("p3_pclk12", "per3clk", clkrst3_base, + clk = clk_reg_prcc_pclk("p3_pclk12", "per3clk", bases[CLKRST3_INDEX], BIT(12), 0); clk_register_clkdev(clk, "apb_pclk", "uart4"); /* Peripheral 5 : PRCC P-clocks */ - clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base, + clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", bases[CLKRST5_INDEX], BIT(0), 0); clk_register_clkdev(clk, "usb", "musb-ux500.0"); clk_register_clkdev(clk, "usbclk", "ab-iddet.0"); - clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base, + clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", bases[CLKRST5_INDEX], BIT(1), 0); clk_register_clkdev(clk, NULL, "gpio.8"); clk_register_clkdev(clk, NULL, "gpioblock3"); /* Peripheral 6 : PRCC P-clocks */ - clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", bases[CLKRST6_INDEX], BIT(0), 0); clk_register_clkdev(clk, "apb_pclk", "rng"); - clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", bases[CLKRST6_INDEX], BIT(1), 0); clk_register_clkdev(clk, NULL, "cryp0"); clk_register_clkdev(clk, NULL, "cryp1"); - clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", bases[CLKRST6_INDEX], BIT(2), 0); clk_register_clkdev(clk, NULL, "hash0"); - clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", bases[CLKRST6_INDEX], BIT(3), 0); clk_register_clkdev(clk, NULL, "pka"); - clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", bases[CLKRST6_INDEX], BIT(4), 0); clk_register_clkdev(clk, NULL, "db8540-hash1"); - clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", bases[CLKRST6_INDEX], BIT(5), 0); clk_register_clkdev(clk, NULL, "cfgreg"); - clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", bases[CLKRST6_INDEX], BIT(6), 0); clk_register_clkdev(clk, "apb_pclk", "mtu0"); - clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base, + clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", bases[CLKRST6_INDEX], BIT(7), 0); clk_register_clkdev(clk, "apb_pclk", "mtu1"); @@ -441,138 +476,138 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, /* Peripheral 1 : PRCC K-clocks */ clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk", - clkrst1_base, BIT(0), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(0), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "uart0"); clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk", - clkrst1_base, BIT(1), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(1), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "uart1"); clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk", - clkrst1_base, BIT(2), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(2), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "nmk-i2c.1"); clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk", - clkrst1_base, BIT(3), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(3), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "msp0"); clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.0"); clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk", - clkrst1_base, BIT(4), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(4), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "msp1"); clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.1"); clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmchclk", - clkrst1_base, BIT(5), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(5), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "sdi0"); clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk", - clkrst1_base, BIT(6), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(6), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "nmk-i2c.2"); clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk", - clkrst1_base, BIT(8), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(8), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "slimbus0"); clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk", - clkrst1_base, BIT(9), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(9), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "nmk-i2c.4"); clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk", - clkrst1_base, BIT(10), CLK_SET_RATE_GATE); + bases[CLKRST1_INDEX], BIT(10), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "msp3"); clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.3"); /* Peripheral 2 : PRCC K-clocks */ clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk", - clkrst2_base, BIT(0), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(0), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "nmk-i2c.3"); clk = clk_reg_prcc_kclk("p2_pwl_kclk", "rtc32k", - clkrst2_base, BIT(1), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(1), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "pwl"); clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmchclk", - clkrst2_base, BIT(2), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(2), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "sdi4"); clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk", - clkrst2_base, BIT(3), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(3), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "msp2"); clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.2"); clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmchclk", - clkrst2_base, BIT(4), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(4), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "sdi1"); clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk", - clkrst2_base, BIT(5), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(5), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "sdi3"); clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk", - clkrst2_base, BIT(6), + bases[CLKRST2_INDEX], BIT(6), CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); clk_register_clkdev(clk, "hsir_hsirxclk", "ste_hsi.0"); clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk", - clkrst2_base, BIT(7), + bases[CLKRST2_INDEX], BIT(7), CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT); clk_register_clkdev(clk, "hsit_hsitxclk", "ste_hsi.0"); /* Should only be 9540, but might be added for 85xx as well */ clk = clk_reg_prcc_kclk("p2_msp4_kclk", "msp02clk", - clkrst2_base, BIT(9), CLK_SET_RATE_GATE); + bases[CLKRST2_INDEX], BIT(9), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "msp4"); clk_register_clkdev(clk, "msp4", "ab85xx-codec.0"); /* Peripheral 3 : PRCC K-clocks */ clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk", - clkrst3_base, BIT(1), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(1), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "ssp0"); clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk", - clkrst3_base, BIT(2), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(2), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "ssp1"); clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk", - clkrst3_base, BIT(3), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(3), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "nmk-i2c.0"); clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmchclk", - clkrst3_base, BIT(4), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(4), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "sdi2"); clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k", - clkrst3_base, BIT(5), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(5), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "ske"); clk_register_clkdev(clk, NULL, "nmk-ske-keypad"); clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk", - clkrst3_base, BIT(6), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(6), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "uart2"); clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk", - clkrst3_base, BIT(7), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(7), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "sdi5"); clk = clk_reg_prcc_kclk("p3_i2c5_kclk", "i2cclk", - clkrst3_base, BIT(8), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(8), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "nmk-i2c.5"); clk = clk_reg_prcc_kclk("p3_i2c6_kclk", "i2cclk", - clkrst3_base, BIT(9), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(9), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "nmk-i2c.6"); clk = clk_reg_prcc_kclk("p3_uart3_kclk", "uartclk", - clkrst3_base, BIT(10), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(10), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "uart3"); clk = clk_reg_prcc_kclk("p3_uart4_kclk", "uartclk", - clkrst3_base, BIT(11), CLK_SET_RATE_GATE); + bases[CLKRST3_INDEX], BIT(11), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "uart4"); /* Peripheral 6 : PRCC K-clocks */ clk = clk_reg_prcc_kclk("p6_rng_kclk", "rngclk", - clkrst6_base, BIT(0), CLK_SET_RATE_GATE); + bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE); clk_register_clkdev(clk, NULL, "rng"); } diff --git a/drivers/clk/ux500/u9540_clk.c b/drivers/clk/ux500/u9540_clk.c index 179bd3871b34..2138a4c8cbca 100644 --- a/drivers/clk/ux500/u9540_clk.c +++ b/drivers/clk/ux500/u9540_clk.c @@ -12,8 +12,7 @@ #include #include "clk.h" -void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, - u32 clkrst5_base, u32 clkrst6_base) +void u9540_clk_init(void) { /* register clocks here */ } diff --git a/include/linux/platform_data/clk-ux500.h b/include/linux/platform_data/clk-ux500.h index 0058edb24391..3af0da1f3be5 100644 --- a/include/linux/platform_data/clk-ux500.h +++ b/include/linux/platform_data/clk-ux500.h @@ -10,12 +10,8 @@ #ifndef __CLK_UX500_H #define __CLK_UX500_H -void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, - u32 clkrst5_base, u32 clkrst6_base); - -void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, - u32 clkrst5_base, u32 clkrst6_base); -void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base, - u32 clkrst5_base, u32 clkrst6_base); +void u8500_clk_init(void); +void u9540_clk_init(void); +void u8540_clk_init(void); #endif /* __CLK_UX500_H */ -- cgit v1.2.3 From fe009175ae3ec3724c1414440e22a1d32d806ec5 Mon Sep 17 00:00:00 2001 From: Milo Kim Date: Mon, 20 Jul 2015 15:45:38 +0900 Subject: backlight: lp855x: Use private data for regulator control LP855x backlight device can be enabled by external VDD input. The 'supply' data is used for this purpose. It's kind of private data which runs internally, so there is no reason to expose to the platform data. And devm_regulator_get() is moved from _parse_dt() to _probe(). Regulator consumer(lp855x) can control regulator not only from DT but also from platform data configuration in a source file such like board-*.c. Signed-off-by: Milo Kim Acked-by: Sean Paul Acked-by: Jingoo Han Signed-off-by: Lee Jones --- drivers/video/backlight/lp855x_bl.c | 23 ++++++++++++----------- include/linux/platform_data/lp855x.h | 2 -- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'include/linux/platform_data') diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index 88116b493f3b..f88df9ec08d0 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -73,6 +73,7 @@ struct lp855x { struct device *dev; struct lp855x_platform_data *pdata; struct pwm_device *pwm; + struct regulator *supply; /* regulator for VDD input */ }; static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data) @@ -378,13 +379,6 @@ static int lp855x_parse_dt(struct lp855x *lp) pdata->rom_data = &rom[0]; } - pdata->supply = devm_regulator_get(dev, "power"); - if (IS_ERR(pdata->supply)) { - if (PTR_ERR(pdata->supply) == -EPROBE_DEFER) - return -EPROBE_DEFER; - pdata->supply = NULL; - } - lp->pdata = pdata; return 0; @@ -425,8 +419,15 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) else lp->mode = REGISTER_BASED; - if (lp->pdata->supply) { - ret = regulator_enable(lp->pdata->supply); + lp->supply = devm_regulator_get(lp->dev, "power"); + if (IS_ERR(lp->supply)) { + if (PTR_ERR(lp->supply) == -EPROBE_DEFER) + return -EPROBE_DEFER; + lp->supply = NULL; + } + + if (lp->supply) { + ret = regulator_enable(lp->supply); if (ret < 0) { dev_err(&cl->dev, "failed to enable supply: %d\n", ret); return ret; @@ -464,8 +465,8 @@ static int lp855x_remove(struct i2c_client *cl) lp->bl->props.brightness = 0; backlight_update_status(lp->bl); - if (lp->pdata->supply) - regulator_disable(lp->pdata->supply); + if (lp->supply) + regulator_disable(lp->supply); sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group); return 0; diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h index 9c7fd1efe495..1b2ba24e4e03 100644 --- a/include/linux/platform_data/lp855x.h +++ b/include/linux/platform_data/lp855x.h @@ -136,7 +136,6 @@ struct lp855x_rom_data { Only valid when mode is PWM_BASED. * @size_program : total size of lp855x_rom_data * @rom_data : list of new eeprom/eprom registers - * @supply : regulator that supplies 3V input */ struct lp855x_platform_data { const char *name; @@ -145,7 +144,6 @@ struct lp855x_platform_data { unsigned int period_ns; int size_program; struct lp855x_rom_data *rom_data; - struct regulator *supply; }; #endif -- cgit v1.2.3 From d407e30ba614b1542c8ac032f8fb2332b8071efe Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Tue, 11 Aug 2015 19:38:27 +0800 Subject: mmc: sdhci-esdhc-imx: add tuning-step setting support tuning-step is the delay cell steps in tuning procedure. The default value of tuning-step is 1. Some boards or cards need another value to pass the tuning procedure. For example, imx7d-sdb board need the tuning-step value as 2, otherwise it can't pass the tuning procedure. So this patch add the tuning-step setting in driver, so that user can set the tuning-step value in dts. Signed-off-by: Haibo Chen Acked-by: Dong Aisheng Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 9 +++++++++ include/linux/platform_data/mmc-esdhc-imx.h | 1 + 2 files changed, 10 insertions(+) (limited to 'include/linux/platform_data') diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index b8b7e8842ed0..298551d00fa4 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -75,6 +75,7 @@ #define ESDHC_STD_TUNING_EN (1 << 24) /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ #define ESDHC_TUNING_START_TAP 0x1 +#define ESDHC_TUNING_STEP_SHIFT 16 /* pinctrl state */ #define ESDHC_PINCTRL_STATE_100MHZ "state_100mhz" @@ -474,6 +475,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); + u32 tuning_ctrl; if (val & SDHCI_CTRL_TUNED_CLK) { v |= ESDHC_MIX_CTRL_SMPCLK_SEL; } else { @@ -484,6 +486,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) if (val & SDHCI_CTRL_EXEC_TUNING) { v |= ESDHC_MIX_CTRL_EXE_TUNE; m |= ESDHC_MIX_CTRL_FBCLK_SEL; + tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL); + tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP; + if (imx_data->boarddata.tuning_step) + tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT; + writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL); } else { v &= ~ESDHC_MIX_CTRL_EXE_TUNE; } @@ -963,6 +970,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, if (gpio_is_valid(boarddata->wp_gpio)) boarddata->wp_type = ESDHC_WP_GPIO; + of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step); + if (of_find_property(np, "no-1-8-v", NULL)) boarddata->support_vsel = false; else diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h index e1571efa3f2b..95ccab3f454a 100644 --- a/include/linux/platform_data/mmc-esdhc-imx.h +++ b/include/linux/platform_data/mmc-esdhc-imx.h @@ -45,5 +45,6 @@ struct esdhc_platform_data { int max_bus_width; bool support_vsel; unsigned int delay_line; + unsigned int tuning_step; /* The delay cell steps in tuning procedure */ }; #endif /* __ASM_ARCH_IMX_ESDHC_H */ -- cgit v1.2.3 From f7fafd083ccc340502448903aaddc76f10785c8c Mon Sep 17 00:00:00 2001 From: Vincent Donnefort Date: Thu, 2 Jul 2015 19:56:40 +0200 Subject: leds: leds-ns2: move LED modes mapping outside of the driver On the board n090401 (Seagate NAS 4-Bay), the LED mode mapping (GPIO values to LED mode) is different from the one used on other boards supported by the leds-ns2 driver. With this patch the hardcoded mapping is removed from leds-ns2. Now, it must be defined either in the platform data (if an old-fashion board setup file is used) or in the DT node. In order to allow the later, this patch also introduces a modes-map property for the leds-ns2 DT binding. Signed-off-by: Vincent Donnefort Signed-off-by: Jacek Anaszewski --- .../devicetree/bindings/leds/leds-ns2.txt | 9 ++ drivers/leds/leds-ns2.c | 102 +++++++++++---------- include/dt-bindings/leds/leds-ns2.h | 8 ++ include/linux/platform_data/leds-kirkwood-ns2.h | 14 +++ 4 files changed, 85 insertions(+), 48 deletions(-) create mode 100644 include/dt-bindings/leds/leds-ns2.h (limited to 'include/linux/platform_data') diff --git a/Documentation/devicetree/bindings/leds/leds-ns2.txt b/Documentation/devicetree/bindings/leds/leds-ns2.txt index aef3aca34d2d..9f81258a5b6e 100644 --- a/Documentation/devicetree/bindings/leds/leds-ns2.txt +++ b/Documentation/devicetree/bindings/leds/leds-ns2.txt @@ -8,6 +8,9 @@ Each LED is represented as a sub-node of the ns2-leds device. Required sub-node properties: - cmd-gpio: Command LED GPIO. See OF device-tree GPIO specification. - slow-gpio: Slow LED GPIO. See OF device-tree GPIO specification. +- modes-map: A mapping between LED modes (off, on or SATA activity blinking) and + the corresponding cmd-gpio/slow-gpio values. All the GPIO values combinations + should be given in order to avoid having an unknown mode at driver probe time. Optional sub-node properties: - label: Name for this LED. If omitted, the label is taken from the node name. @@ -15,6 +18,8 @@ Optional sub-node properties: Example: +#include + ns2-leds { compatible = "lacie,ns2-leds"; @@ -22,5 +27,9 @@ ns2-leds { label = "ns2:blue:sata"; slow-gpio = <&gpio0 29 0>; cmd-gpio = <&gpio0 30 0>; + modes-map = ; }; }; diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 1fd6adbb43b7..b0bc03539dbb 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -33,46 +33,20 @@ #include /* - * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in - * relation with the SATA activity. This capability is exposed through the - * "sata" sysfs attribute. - * - * The following array detail the different LED registers and the combination - * of their possible values: - * - * cmd_led | slow_led | /SATA active | LED state - * | | | - * 1 | 0 | x | off - * - | 1 | x | on - * 0 | 0 | 1 | on - * 0 | 0 | 0 | blink (rate 300ms) + * The Network Space v2 dual-GPIO LED is wired to a CPLD. Three different LED + * modes are available: off, on and SATA activity blinking. The LED modes are + * controlled through two GPIOs (command and slow): each combination of values + * for the command/slow GPIOs corresponds to a LED mode. */ -enum ns2_led_modes { - NS_V2_LED_OFF, - NS_V2_LED_ON, - NS_V2_LED_SATA, -}; - -struct ns2_led_mode_value { - enum ns2_led_modes mode; - int cmd_level; - int slow_level; -}; - -static struct ns2_led_mode_value ns2_led_modval[] = { - { NS_V2_LED_OFF , 1, 0 }, - { NS_V2_LED_ON , 0, 1 }, - { NS_V2_LED_ON , 1, 1 }, - { NS_V2_LED_SATA, 0, 0 }, -}; - struct ns2_led_data { struct led_classdev cdev; unsigned cmd; unsigned slow; unsigned char sata; /* True when SATA mode active. */ rwlock_t rw_lock; /* Lock GPIOs. */ + int num_modes; + struct ns2_led_modval *modval; }; static int ns2_led_get_mode(struct ns2_led_data *led_dat, @@ -88,10 +62,10 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat, cmd_level = gpio_get_value(led_dat->cmd); slow_level = gpio_get_value(led_dat->slow); - for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) { - if (cmd_level == ns2_led_modval[i].cmd_level && - slow_level == ns2_led_modval[i].slow_level) { - *mode = ns2_led_modval[i].mode; + for (i = 0; i < led_dat->num_modes; i++) { + if (cmd_level == led_dat->modval[i].cmd_level && + slow_level == led_dat->modval[i].slow_level) { + *mode = led_dat->modval[i].mode; ret = 0; break; } @@ -110,12 +84,12 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat, write_lock_irqsave(&led_dat->rw_lock, flags); - for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) { - if (mode == ns2_led_modval[i].mode) { + for (i = 0; i < led_dat->num_modes; i++) { + if (mode == led_dat->modval[i].mode) { gpio_set_value(led_dat->cmd, - ns2_led_modval[i].cmd_level); + led_dat->modval[i].cmd_level); gpio_set_value(led_dat->slow, - ns2_led_modval[i].slow_level); + led_dat->modval[i].slow_level); } } @@ -228,6 +202,8 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, led_dat->cdev.groups = ns2_led_groups; led_dat->cmd = template->cmd; led_dat->slow = template->slow; + led_dat->modval = template->modval; + led_dat->num_modes = template->num_modes; ret = ns2_led_get_mode(led_dat, &mode); if (ret < 0) @@ -259,9 +235,8 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) { struct device_node *np = dev->of_node; struct device_node *child; - struct ns2_led *leds; + struct ns2_led *led, *leds; int num_leds = 0; - int i = 0; num_leds = of_get_child_count(np); if (!num_leds) @@ -272,26 +247,57 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata) if (!leds) return -ENOMEM; + led = leds; for_each_child_of_node(np, child) { const char *string; - int ret; + int ret, i, num_modes; + struct ns2_led_modval *modval; ret = of_get_named_gpio(child, "cmd-gpio", 0); if (ret < 0) return ret; - leds[i].cmd = ret; + led->cmd = ret; ret = of_get_named_gpio(child, "slow-gpio", 0); if (ret < 0) return ret; - leds[i].slow = ret; + led->slow = ret; ret = of_property_read_string(child, "label", &string); - leds[i].name = (ret == 0) ? string : child->name; + led->name = (ret == 0) ? string : child->name; ret = of_property_read_string(child, "linux,default-trigger", &string); if (ret == 0) - leds[i].default_trigger = string; + led->default_trigger = string; + + ret = of_property_count_u32_elems(child, "modes-map"); + if (ret < 0 || ret % 3) { + dev_err(dev, + "Missing or malformed modes-map property\n"); + return -EINVAL; + } + + num_modes = ret / 3; + modval = devm_kzalloc(dev, + num_modes * sizeof(struct ns2_led_modval), + GFP_KERNEL); + if (!modval) + return -ENOMEM; + + for (i = 0; i < num_modes; i++) { + of_property_read_u32_index(child, + "modes-map", 3 * i, + (u32 *) &modval[i].mode); + of_property_read_u32_index(child, + "modes-map", 3 * i + 1, + (u32 *) &modval[i].cmd_level); + of_property_read_u32_index(child, + "modes-map", 3 * i + 2, + (u32 *) &modval[i].slow_level); + } + + led->num_modes = num_modes; + led->modval = modval; - i++; + led++; } pdata->leds = leds; diff --git a/include/dt-bindings/leds/leds-ns2.h b/include/dt-bindings/leds/leds-ns2.h new file mode 100644 index 000000000000..491c5f974a92 --- /dev/null +++ b/include/dt-bindings/leds/leds-ns2.h @@ -0,0 +1,8 @@ +#ifndef _DT_BINDINGS_LEDS_NS2_H +#define _DT_BINDINGS_LEDS_NS2_H + +#define NS_V2_LED_OFF 0 +#define NS_V2_LED_ON 1 +#define NS_V2_LED_SATA 2 + +#endif diff --git a/include/linux/platform_data/leds-kirkwood-ns2.h b/include/linux/platform_data/leds-kirkwood-ns2.h index 6a9fed57f346..eb8a6860e816 100644 --- a/include/linux/platform_data/leds-kirkwood-ns2.h +++ b/include/linux/platform_data/leds-kirkwood-ns2.h @@ -9,11 +9,25 @@ #ifndef __LEDS_KIRKWOOD_NS2_H #define __LEDS_KIRKWOOD_NS2_H +enum ns2_led_modes { + NS_V2_LED_OFF, + NS_V2_LED_ON, + NS_V2_LED_SATA, +}; + +struct ns2_led_modval { + enum ns2_led_modes mode; + int cmd_level; + int slow_level; +}; + struct ns2_led { const char *name; const char *default_trigger; unsigned cmd; unsigned slow; + int num_modes; + struct ns2_led_modval *modval; }; struct ns2_led_platform_data { -- cgit v1.2.3