diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/vexpress/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/vexpress/clk-sp810.c | 136 | ||||
-rw-r--r-- | drivers/clk/vexpress/clk-vexpress-osc.c | 42 | ||||
-rw-r--r-- | drivers/clocksource/amba-sp804.c | 4 | ||||
-rw-r--r-- | drivers/eeprom/at24.c | 2 | ||||
-rw-r--r-- | drivers/efi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mci/mmci.c | 39 | ||||
-rw-r--r-- | drivers/net/e1000/e1000.h | 9 | ||||
-rw-r--r-- | drivers/net/e1000/eeprom.c | 27 | ||||
-rw-r--r-- | drivers/net/e1000/regio.c | 9 | ||||
-rw-r--r-- | drivers/of/base.c | 18 |
12 files changed, 255 insertions, 35 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index ddd971c607..55ac9535a5 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_SOC_QCA_AR9331) += clk-ar933x.o obj-$(CONFIG_SOC_QCA_AR9344) += clk-ar9344.o obj-$(CONFIG_ARCH_IMX) += imx/ obj-$(CONFIG_COMMON_CLK_AT91) += at91/ +obj-$(CONFIG_MACH_VEXPRESS) += vexpress/ diff --git a/drivers/clk/vexpress/Makefile b/drivers/clk/vexpress/Makefile new file mode 100644 index 0000000000..c6869bac83 --- /dev/null +++ b/drivers/clk/vexpress/Makefile @@ -0,0 +1 @@ +obj-y += clk-vexpress-osc.o clk-sp810.o diff --git a/drivers/clk/vexpress/clk-sp810.c b/drivers/clk/vexpress/clk-sp810.c new file mode 100644 index 0000000000..af72c74024 --- /dev/null +++ b/drivers/clk/vexpress/clk-sp810.c @@ -0,0 +1,136 @@ +/* + * 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. + * + * Copyright (C) 2013 ARM Limited + */ + +#include <common.h> +#include <io.h> +#include <malloc.h> +#include <of_address.h> +#include <linux/clk.h> +#include <linux/err.h> + +/* sysctl registers offset */ +#define SCCTRL 0x000 +#define SCCTRL_TIMERENnSEL_SHIFT(n) (15 + ((n) * 2)) + +struct clk_sp810; + +struct clk_sp810_timerclken { + struct clk hw; + struct clk_sp810 *sp810; + int channel; +}; + +static inline struct clk_sp810_timerclken * +to_clk_sp810_timerclken(struct clk *clk) +{ + return container_of(clk, struct clk_sp810_timerclken, hw); +} + +struct clk_sp810 { + struct device_node *node; + void __iomem *base; + struct clk_sp810_timerclken timerclken[4]; +}; + +static int clk_sp810_timerclken_get_parent(struct clk *hw) +{ + struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); + u32 val = readl(timerclken->sp810->base + SCCTRL); + + return !!(val & (1 << SCCTRL_TIMERENnSEL_SHIFT(timerclken->channel))); +} + +static int clk_sp810_timerclken_set_parent(struct clk *hw, u8 index) +{ + struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); + struct clk_sp810 *sp810 = timerclken->sp810; + u32 val, shift = SCCTRL_TIMERENnSEL_SHIFT(timerclken->channel); + + if (WARN_ON(index > 1)) + return -EINVAL; + + val = readl(sp810->base + SCCTRL); + val &= ~(1 << shift); + val |= index << shift; + writel(val, sp810->base + SCCTRL); + + return 0; +} + +static const struct clk_ops clk_sp810_timerclken_ops = { + .get_parent = clk_sp810_timerclken_get_parent, + .set_parent = clk_sp810_timerclken_set_parent, +}; + +static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec, + void *data) +{ + struct clk_sp810 *sp810 = data; + + if (WARN_ON(clkspec->args_count != 1 || + clkspec->args[0] >= ARRAY_SIZE(sp810->timerclken))) + return NULL; + + return &sp810->timerclken[clkspec->args[0]].hw; +} + +static void clk_sp810_of_setup(struct device_node *node) +{ + struct clk_sp810 *sp810 = xzalloc(sizeof(*sp810)); + const char *parent_names[2]; + int num = ARRAY_SIZE(parent_names); + char name[12]; + static int instance; + int i; + bool deprecated; + + if (!sp810) + return; + + if (of_clk_parent_fill(node, parent_names, num) != num) { + pr_warn("Failed to obtain parent clocks for SP810!\n"); + kfree(sp810); + return; + } + + sp810->node = node; + sp810->base = of_iomap(node, 0); + + deprecated = !of_find_property(node, "assigned-clock-parents", NULL); + + for (i = 0; i < ARRAY_SIZE(sp810->timerclken); i++) { + snprintf(name, sizeof(name), "sp810_%d_%d", instance, i); + + sp810->timerclken[i].sp810 = sp810; + sp810->timerclken[i].channel = i; + sp810->timerclken[i].hw.name = strdup(name); + sp810->timerclken[i].hw.parent_names = parent_names; + sp810->timerclken[i].hw.num_parents = num; + sp810->timerclken[i].hw.ops = &clk_sp810_timerclken_ops; + + /* + * If DT isn't setting the parent, force it to be + * the 1 MHz clock without going through the framework. + * We do this before clk_register() so that it can determine + * the parent and setup the tree properly. + */ + if (deprecated) + clk_sp810_timerclken_set_parent(&sp810->timerclken[i].hw, 1); + + clk_register(&sp810->timerclken[i].hw); + } + + of_clk_add_provider(node, clk_sp810_timerclken_of_get, sp810); + instance++; +} +CLK_OF_DECLARE(sp810, "arm,sp810", clk_sp810_of_setup); diff --git a/drivers/clk/vexpress/clk-vexpress-osc.c b/drivers/clk/vexpress/clk-vexpress-osc.c new file mode 100644 index 0000000000..c0d6e6066e --- /dev/null +++ b/drivers/clk/vexpress/clk-vexpress-osc.c @@ -0,0 +1,42 @@ +/* + * 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 <common.h> +#include <malloc.h> +#include <linux/clk.h> +#include <linux/err.h> + +/* + * This represents the vexpress-osc as a fixed clock, which isn't really + * accurate, as this clock allows rate changes in real implementations. As those + * would need access to the config bus, a whole lot more infrastructure would be + * needed. We skip this complication for now, as we don't have a use-case, yet. + */ +static int vexpress_osc_setup(struct device_node *node) +{ + struct clk *clk; + u32 range[2]; + const char *name; + + if (of_property_read_u32_array(node, "freq-range", range, + ARRAY_SIZE(range))) + return -EINVAL; + + if (of_property_read_string(node, "clock-output-names", &name)) + return -EINVAL; + + clk = clk_fixed(name, range[0]); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + return of_clk_add_provider(node, of_clk_src_simple_get, clk); +} +CLK_OF_DECLARE(vexpress_osc, "arm,vexpress-osc", vexpress_osc_setup); diff --git a/drivers/clocksource/amba-sp804.c b/drivers/clocksource/amba-sp804.c index c5ad9947cd..66e3988b4c 100644 --- a/drivers/clocksource/amba-sp804.c +++ b/drivers/clocksource/amba-sp804.c @@ -35,8 +35,8 @@ static int sp804_probe(struct amba_device *dev, const struct amba_id *id) int ret; if (sp804_base) { - dev_err(&dev->dev, "single instance driver\n"); - return -EBUSY; + dev_dbg(&dev->dev, "skipping secondary instance\n"); + return 0; } sp804_clk = clk_get(&dev->dev, NULL); diff --git a/drivers/eeprom/at24.c b/drivers/eeprom/at24.c index 050a35aed8..11f23319b6 100644 --- a/drivers/eeprom/at24.c +++ b/drivers/eeprom/at24.c @@ -352,7 +352,7 @@ static ssize_t at24_cdev_write(struct cdev *cdev, const void *buf, size_t count, return at24_write(at24, buf, off, count); } -static ssize_t at24_cdev_protect(struct cdev *cdev, size_t count, loff_t offset, +static int at24_cdev_protect(struct cdev *cdev, size_t count, loff_t offset, int prot) { struct at24_data *at24 = cdev->priv; diff --git a/drivers/efi/Kconfig b/drivers/efi/Kconfig index 2cd9dd504f..cca1a2e1d6 100644 --- a/drivers/efi/Kconfig +++ b/drivers/efi/Kconfig @@ -1,2 +1,4 @@ config EFI_BOOTUP bool + select BLOCK + select PARTITION_DISK diff --git a/drivers/mci/mmci.c b/drivers/mci/mmci.c index 7489ee03a1..f45557d4f7 100644 --- a/drivers/mci/mmci.c +++ b/drivers/mci/mmci.c @@ -532,9 +532,37 @@ static void mci_set_ios(struct mci_host *mci, struct mci_ios *ios) udelay(CLK_CHANGE_DELAY); } +static int mmci_of_parse(struct device_node *np, + struct mmci_platform_data *plat) +{ + if (!IS_ENABLED(CONFIG_OFDEVICE)) + return 0; + + if (of_get_property(np, "st,sig-dir-dat0", NULL)) + plat->sigdir |= MCI_ST_DATA0DIREN; + if (of_get_property(np, "st,sig-dir-dat2", NULL)) + plat->sigdir |= MCI_ST_DATA2DIREN; + if (of_get_property(np, "st,sig-dir-dat31", NULL)) + plat->sigdir |= MCI_ST_DATA31DIREN; + if (of_get_property(np, "st,sig-dir-dat74", NULL)) + plat->sigdir |= MCI_ST_DATA74DIREN; + if (of_get_property(np, "st,sig-dir-cmd", NULL)) + plat->sigdir |= MCI_ST_CMDDIREN; + if (of_get_property(np, "st,sig-pin-fbclk", NULL)) + plat->sigdir |= MCI_ST_FBCLKEN; + + if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL)) + plat->capabilities |= MMC_CAP_MMC_HIGHSPEED; + if (of_get_property(np, "mmc-cap-sd-highspeed", NULL)) + plat->capabilities |= MMC_CAP_SD_HIGHSPEED; + + return 0; +} + static int mmci_probe(struct amba_device *dev, const struct amba_id *id) { struct device_d *hw_dev = &dev->dev; + struct device_node *np = hw_dev->device_node; struct mmci_platform_data *plat = hw_dev->platform_data; struct variant_data *variant = id->data; u32 sdi_u32; @@ -542,11 +570,16 @@ static int mmci_probe(struct amba_device *dev, const struct amba_id *id) struct clk *clk; int ret; - if (!plat) { - dev_err(hw_dev, "missing platform data\n"); + if (!plat && !np) { + dev_err(hw_dev, "missing platform data or DT node\n"); return -EINVAL; } + if (!plat) + plat = xzalloc(sizeof(*plat)); + + mmci_of_parse(np, plat); + host = xzalloc(sizeof(*host)); host->base = amba_get_mem_region(dev); @@ -625,7 +658,7 @@ static int mmci_probe(struct amba_device *dev, const struct amba_id *id) host->mci.max_req_size = (1 << variant->datalength_bits) - 1; host->mci.host_caps = plat->capabilities; - host->mci.voltages = plat->ocr_mask; + host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | plat->ocr_mask; mci_register(&host->mci); diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index e6b493c84c..f2da08b4d5 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -447,11 +447,11 @@ struct e1000_tx_desc { #define E1000_FLASHT 0x01028 /* FLASH Timer Register */ #define E1000_EEWR (E1000_MIGHT_BE_REMAPPED | 0x0102C) /* EEPROM Write Register - RW */ #define E1000_I210_EEWR 0x12018 /* EEPROM Write Register - RW */ -#define E1000_FLSWCTL 0x01030 /* FLASH control register */ +#define E1000_FLSWCTL (E1000_MIGHT_BE_REMAPPED | 0x01030) /* FLASH control register */ #define E1000_I210_FLSWCTL 0x12048 /* FLASH control register */ -#define E1000_FLSWDATA 0x01034 /* FLASH data register */ +#define E1000_FLSWDATA (E1000_MIGHT_BE_REMAPPED | 0x01034) /* FLASH data register */ #define E1000_I210_FLSWDATA 0x1204C /* FLASH data register */ -#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ +#define E1000_FLSWCNT (E1000_MIGHT_BE_REMAPPED | 0x01038) /* FLASH Access Counter */ #define E1000_I210_FLSWCNT 0x12050 /* FLASH Access Counter */ #define E1000_FLOP 0x0103C /* FLASH Opcode Register */ #define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ @@ -2105,9 +2105,6 @@ struct e1000_eeprom_info { #define E1000_FLA 0x1201C #define E1000_FLA_FL_SIZE_SHIFT 17 #define E1000_FLA_FL_SIZE_MASK (0b111 << E1000_FLA_FL_SIZE_SHIFT) /* EEprom Size */ -#define E1000_FLA_FL_SIZE_2MB 0b101 -#define E1000_FLA_FL_SIZE_4MB 0b110 -#define E1000_FLA_FL_SIZE_8MB 0b111 #define E1000_FLSWCTL_ADDR(a) ((a) & 0x00FFFFFF) diff --git a/drivers/net/e1000/eeprom.c b/drivers/net/e1000/eeprom.c index 1a0c6e15ab..2a71fb1b15 100644 --- a/drivers/net/e1000/eeprom.c +++ b/drivers/net/e1000/eeprom.c @@ -414,17 +414,9 @@ int32_t e1000_init_eeprom_params(struct e1000_hw *hw) fla &= E1000_FLA_FL_SIZE_MASK; fla >>= E1000_FLA_FL_SIZE_SHIFT; - switch (fla) { - case E1000_FLA_FL_SIZE_8MB: - eeprom->word_size = SZ_8M / 2; - break; - case E1000_FLA_FL_SIZE_4MB: - eeprom->word_size = SZ_4M / 2; - break; - case E1000_FLA_FL_SIZE_2MB: - eeprom->word_size = SZ_2M / 2; - break; - default: + if (fla) { + eeprom->word_size = (SZ_64K << fla) / 2; + } else { eeprom->word_size = 2048; dev_info(hw->dev, "Unprogrammed Flash detected, " "limiting access to first 4KB\n"); @@ -709,17 +701,8 @@ static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw) static int e1000_flash_mode_wait_for_idle(struct e1000_hw *hw) { - /* Strictly speaking we need to poll FLSWCTL.DONE only if we - * are executing this code after a reset event, but it - * shouldn't hurt to do this everytime, besided we need to - * poll got FLSWCTL.GLDONE to make sure that back to back - * calls to that function work correctly, since we finish - * execution by polling only FLSWCTL.DONE */ - - const int ret = e1000_poll_reg(hw, E1000_FLSWCTL, - E1000_FLSWCTL_DONE | E1000_FLSWCTL_GLDONE, - E1000_FLSWCTL_DONE | E1000_FLSWCTL_GLDONE, - SECOND); + const int ret = e1000_poll_reg(hw, E1000_FLSWCTL, E1000_FLSWCTL_DONE, + E1000_FLSWCTL_DONE, SECOND); if (ret < 0) dev_err(hw->dev, "Timeout waiting for FLSWCTL.DONE to be set\n"); diff --git a/drivers/net/e1000/regio.c b/drivers/net/e1000/regio.c index 1610d5851f..5b2740fbc2 100644 --- a/drivers/net/e1000/regio.c +++ b/drivers/net/e1000/regio.c @@ -16,6 +16,15 @@ static uint32_t e1000_true_offset(struct e1000_hw *hw, uint32_t reg) case E1000_EEMNGCTL: reg = E1000_I210_EEMNGCTL; break; + case E1000_FLSWCTL: + reg = E1000_I210_FLSWCTL; + break; + case E1000_FLSWCNT: + reg = E1000_I210_FLSWCNT; + break; + case E1000_FLSWDATA: + reg = E1000_I210_FLSWDATA; + break; } } reg &= ~E1000_MIGHT_BE_REMAPPED; diff --git a/drivers/of/base.c b/drivers/of/base.c index 95bea4ee83..3ca13ae44e 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1938,8 +1938,8 @@ int of_probe(void) if (memory) of_add_memory(memory, false); - of_platform_populate(root_node, of_default_bus_match_table, NULL); of_clk_init(root_node, NULL); + of_platform_populate(root_node, of_default_bus_match_table, NULL); return 0; } @@ -1988,6 +1988,22 @@ out: return dn; } +struct device_node *of_copy_node(struct device_node *parent, const struct device_node *other) +{ + struct device_node *np, *child; + struct property *pp; + + np = of_new_node(parent, other->name); + + list_for_each_entry(pp, &other->properties, list) + of_new_property(np, pp->name, pp->value, pp->length); + + for_each_child_of_node(other, child) + of_copy_node(np, child); + + return np; +} + void of_delete_node(struct device_node *node) { struct device_node *n, *nt; |