summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig9
-rw-r--r--drivers/misc/Makefile3
-rw-r--r--drivers/misc/fsl_debug_server.c5
-rw-r--r--drivers/misc/pca9551_led.c32
-rw-r--r--drivers/misc/reset-uclass.c81
-rw-r--r--drivers/misc/reset_sandbox.c100
-rw-r--r--drivers/misc/syscon_sandbox.c27
7 files changed, 247 insertions, 10 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 64b07a30155..3b7f76ab787 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -73,3 +73,12 @@ config PCA9551_I2C_ADDR
default 0x60
help
The I2C address of the PCA9551 LED controller.
+
+config RESET
+ bool "Enable support for reset drivers"
+ depends on DM
+ help
+ Enable reset drivers which can be used to reset the CPU or board.
+ Each driver can provide a reset method which will be called to
+ effect a reset. The uclass will try all available drivers when
+ reset_walk() is called.
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 120babc4b5d..5218b91c0ba 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -22,13 +22,16 @@ obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
obj-$(CONFIG_NS87308) += ns87308.o
obj-$(CONFIG_PDSP188x) += pdsp188x.o
+obj-$(CONFIG_SANDBOX) += reset_sandbox.o
ifdef CONFIG_DM_I2C
obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
endif
obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
obj-$(CONFIG_STATUS_LED) += status_led.o
obj-$(CONFIG_SANDBOX) += swap_case.o
+obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
+obj-$(CONFIG_RESET) += reset-uclass.o
diff --git a/drivers/misc/fsl_debug_server.c b/drivers/misc/fsl_debug_server.c
index e080fe61323..44cd9b9fd48 100644
--- a/drivers/misc/fsl_debug_server.c
+++ b/drivers/misc/fsl_debug_server.c
@@ -10,6 +10,7 @@
#include <asm/system.h>
#include <asm/arch-fsl-lsch3/immap_lsch3.h>
+#include <fsl-mc/fsl_mc.h>
#include <fsl_debug_server.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -151,6 +152,10 @@ int debug_server_init(void)
debug_server_ram_addr =
gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
+#ifdef CONFIG_FSL_MC_ENET
+ debug_server_ram_addr += mc_get_dram_block_size();
+#endif
+
error = debug_server_parse_firmware_fit_image(&raw_image_addr,
&raw_image_size);
if (error != 0)
diff --git a/drivers/misc/pca9551_led.c b/drivers/misc/pca9551_led.c
index 79b1e20ccf1..d4034f6735b 100644
--- a/drivers/misc/pca9551_led.c
+++ b/drivers/misc/pca9551_led.c
@@ -32,7 +32,10 @@ struct pca9551_blink_rate {
u8 pwm; /* Pulse width modulation, see PCA9551_7.pdf p. 6 */
};
-static int freq0, freq1;
+static int freq_last = -1;
+static int mask_last = -1;
+static int idx_last = -1;
+static int mode_last;
static int pca9551_led_get_state(int led, int *state)
{
@@ -135,21 +138,30 @@ void __led_blink(led_id_t mask, int freq)
{
struct pca9551_blink_rate rate;
int mode;
- int blink;
+ int idx;
- if ((freq0 == 0) || (freq == freq0)) {
- blink = 0;
- mode = PCA9551_LED_STATE_BLINK0;
- freq0 = freq;
+ if ((freq == freq_last) || (mask == mask_last)) {
+ idx = idx_last;
+ mode = mode_last;
} else {
- blink = 1;
- mode = PCA9551_LED_STATE_BLINK1;
- freq1 = freq;
+ /* Toggle blink index */
+ if (idx_last == 0) {
+ idx = 1;
+ mode = PCA9551_LED_STATE_BLINK1;
+ } else {
+ idx = 0;
+ mode = PCA9551_LED_STATE_BLINK0;
+ }
+
+ idx_last = idx;
+ mode_last = mode;
}
+ freq_last = freq;
+ mask_last = mask;
rate.psc = ((freq * 38) / 1000) - 1;
rate.pwm = 128; /* 50% duty cycle */
- pca9551_led_set_blink_rate(blink, rate);
+ pca9551_led_set_blink_rate(idx, rate);
pca9551_led_set_state(mask, mode);
}
diff --git a/drivers/misc/reset-uclass.c b/drivers/misc/reset-uclass.c
new file mode 100644
index 00000000000..fdb5c6fcff3
--- /dev/null
+++ b/drivers/misc/reset-uclass.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <reset.h>
+#include <dm.h>
+#include <errno.h>
+#include <regmap.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <linux/err.h>
+
+int reset_request(struct udevice *dev, enum reset_t type)
+{
+ struct reset_ops *ops = reset_get_ops(dev);
+
+ if (!ops->request)
+ return -ENOSYS;
+
+ return ops->request(dev, type);
+}
+
+int reset_walk(enum reset_t type)
+{
+ struct udevice *dev;
+ int ret = -ENOSYS;
+
+ while (ret != -EINPROGRESS && type < RESET_COUNT) {
+ for (uclass_first_device(UCLASS_RESET, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ ret = reset_request(dev, type);
+ if (ret == -EINPROGRESS)
+ break;
+ }
+ type++;
+ }
+
+ return ret;
+}
+
+void reset_walk_halt(enum reset_t type)
+{
+ int ret;
+
+ ret = reset_walk(type);
+
+ /* Wait for the reset to take effect */
+ if (ret == -EINPROGRESS)
+ mdelay(100);
+
+ /* Still no reset? Give up */
+ printf("Reset not supported on this platform\n");
+ hang();
+}
+
+/**
+ * reset_cpu() - calls reset_walk(RESET_WARM)
+ */
+void reset_cpu(ulong addr)
+{
+ reset_walk_halt(RESET_WARM);
+}
+
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ reset_walk_halt(RESET_WARM);
+
+ return 0;
+}
+
+UCLASS_DRIVER(reset) = {
+ .id = UCLASS_RESET,
+ .name = "reset",
+};
diff --git a/drivers/misc/reset_sandbox.c b/drivers/misc/reset_sandbox.c
new file mode 100644
index 00000000000..917121bc5e8
--- /dev/null
+++ b/drivers/misc/reset_sandbox.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <reset.h>
+#include <asm/state.h>
+#include <asm/test.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sandbox_warm_reset_request(struct udevice *dev, enum reset_t type)
+{
+ struct sandbox_state *state = state_get_current();
+
+ switch (type) {
+ case RESET_WARM:
+ state->last_reset = type;
+ break;
+ default:
+ return -ENOSYS;
+ }
+ if (!state->reset_allowed[type])
+ return -EACCES;
+
+ return -EINPROGRESS;
+}
+
+static int sandbox_reset_request(struct udevice *dev, enum reset_t type)
+{
+ struct sandbox_state *state = state_get_current();
+
+ /*
+ * If we have a device tree, the device we created from platform data
+ * (see the U_BOOT_DEVICE() declaration below) should not do anything.
+ * If we are that device, return an error.
+ */
+ if (gd->fdt_blob && dev->of_offset == -1)
+ return -ENODEV;
+
+ switch (type) {
+ case RESET_COLD:
+ state->last_reset = type;
+ break;
+ case RESET_POWER:
+ state->last_reset = type;
+ if (!state->reset_allowed[type])
+ return -EACCES;
+ sandbox_exit();
+ break;
+ default:
+ return -ENOSYS;
+ }
+ if (!state->reset_allowed[type])
+ return -EACCES;
+
+ return -EINPROGRESS;
+}
+
+static struct reset_ops sandbox_reset_ops = {
+ .request = sandbox_reset_request,
+};
+
+static const struct udevice_id sandbox_reset_ids[] = {
+ { .compatible = "sandbox,reset" },
+ { }
+};
+
+U_BOOT_DRIVER(reset_sandbox) = {
+ .name = "reset_sandbox",
+ .id = UCLASS_RESET,
+ .of_match = sandbox_reset_ids,
+ .ops = &sandbox_reset_ops,
+};
+
+static struct reset_ops sandbox_warm_reset_ops = {
+ .request = sandbox_warm_reset_request,
+};
+
+static const struct udevice_id sandbox_warm_reset_ids[] = {
+ { .compatible = "sandbox,warm-reset" },
+ { }
+};
+
+U_BOOT_DRIVER(warm_reset_sandbox) = {
+ .name = "warm_reset_sandbox",
+ .id = UCLASS_RESET,
+ .of_match = sandbox_warm_reset_ids,
+ .ops = &sandbox_warm_reset_ops,
+};
+
+/* This is here in case we don't have a device tree */
+U_BOOT_DEVICE(reset_sandbox_non_fdt) = {
+ .name = "reset_sandbox",
+};
diff --git a/drivers/misc/syscon_sandbox.c b/drivers/misc/syscon_sandbox.c
new file mode 100644
index 00000000000..ccfab3ef987
--- /dev/null
+++ b/drivers/misc/syscon_sandbox.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/test.h>
+#include <dm/lists.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct udevice_id sandbox_syscon_ids[] = {
+ { .compatible = "sandbox,syscon0", .data = SYSCON0 },
+ { .compatible = "sandbox,syscon1", .data = SYSCON1 },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_syscon) = {
+ .name = "sandbox_syscon",
+ .id = UCLASS_SYSCON,
+ .of_match = sandbox_syscon_ids,
+};