summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/vexpress/Makefile1
-rw-r--r--drivers/clk/vexpress/clk-sp810.c136
-rw-r--r--drivers/clk/vexpress/clk-vexpress-osc.c42
-rw-r--r--drivers/clocksource/amba-sp804.c4
-rw-r--r--drivers/eeprom/at24.c2
-rw-r--r--drivers/efi/Kconfig2
-rw-r--r--drivers/mci/mmci.c39
-rw-r--r--drivers/net/e1000/e1000.h9
-rw-r--r--drivers/net/e1000/eeprom.c27
-rw-r--r--drivers/net/e1000/regio.c9
-rw-r--r--drivers/of/base.c18
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;