]> rtime.felk.cvut.cz Git - vajnamar/linux-xlnx.git/blobdiff - arch/arm/mach-zynq/slcr.c
Merge tag 'v3.10' into master-next
[vajnamar/linux-xlnx.git] / arch / arm / mach-zynq / slcr.c
index c70969b9c258d47a49880699a621f9e2c58997b3..8b903ec29d49e83603a4e8530c78841f48a25524 100644 (file)
 #define SLCR_UNLOCK_MAGIC              0xDF0D
 #define SLCR_UNLOCK                    0x8   /* SCLR unlock register */
 
+#define DRIVER_NAME "xslcr"
+
+#define XSLCR_LOCK                     0x4   /* SLCR lock register */
+#define XSLCR_UNLOCK                   0x8   /* SCLR unlock register */
+#define XSLCR_PSS_RST_CTRL_OFFSET      0x200 /* PSS Software Reset Control */
+#define XSLCR_DDR_RST_CTRL_OFFSET      0x204 /* DDR Software Reset Control */
+#define XSLCR_AMBA_RST_CTRL_OFFSET     0x208 /* AMBA Software Reset Control */
+#define XSLCR_DMAC_RST_CTRL_OFFSET     0x20C /* DMAC Software Reset Control */
+#define XSLCR_USB_RST_CTRL_OFFSET      0x210 /* USB Software Reset Control */
+#define XSLCR_EMAC_RST_CTRL_OFFSET     0x214 /* EMAC Software Reset Control */
+#define XSLCR_SDIO_RST_CTRL_OFFSET     0x218 /* SDIO Software Reset Control */
+#define XSLCR_SPI_RST_CTRL_OFFSET      0x21C /* SPI Software Reset Control */
+#define XSLCR_CAN_RST_CTRL_OFFSET      0x220 /* CAN Software Reset Control */
+#define XSLCR_I2C_RST_CTRL_OFFSET      0x224 /* I2C Software Reset Control */
+#define XSLCR_UART_RST_CTRL_OFFSET     0x228 /* UART Software Reset Control */
+#define XSLCR_GPIO_RST_CTRL_OFFSET     0x22C /* GPIO Software Reset Control */
+#define XSLCR_QSPI_RST_CTRL_OFFSET     0x230 /* QSpI Software Reset Control */
+#define XSLCR_SMC_RST_CTRL_OFFSET      0x234 /* SMC Software Reset Control */
+#define XSLCR_OCM_RST_CTRL_OFFSET      0x238 /* OCM Software Reset Control */
+#define XSLCR_DEVC_RST_CTRL_OFFSET     0x23C /* Dev Cfg SW Reset Control */
+#define XSLCR_FPGA_RST_CTRL_OFFSET     0x240 /* FPGA Software Reset Control */
+#define XSLCR_A9_CPU_RST_CTRL          0x244 /* CPU Software Reset Control */
+#define XSLCR_REBOOT_STATUS            0x258 /* PS Reboot Status */
+#define XSLCR_MIO_PIN_00_OFFSET                0x700 /* MIO PIN0 control register */
+#define XSLCR_LVL_SHFTR_EN_OFFSET      0x900 /* Level Shifters Enable */
+
+#define XSLCR_MIO_L0_SHIFT             1
+#define XSLCR_MIO_L1_SHIFT             2
+#define XSLCR_MIO_L2_SHIFT             3
+#define XSLCR_MIO_L3_SHIFT             5
+
+#define XSLCR_MIO_LMASK                        0x000000FE
+
+#define XSLCR_MIO_PIN_XX_TRI_ENABLE    0x00000001
+
+/* The following constants define L0 Mux Peripheral Enables */
+#define XSLCR_MIO_PIN_EMAC_ENABLE      (0x01 << XSLCR_MIO_L0_SHIFT)
+#define XSLCR_MIO_PIN_QSPI_ENABLE      (0x01 << XSLCR_MIO_L0_SHIFT)
+
+/* The following constants define L1 Mux Enables */
+#define XSLCR_MIO_PIN_USB_ENABLE       (0x01 << XSLCR_MIO_L1_SHIFT)
+#define XSLCR_MIO_PIN_TRACE_PORT_ENABLE        (0x01 << XSLCR_MIO_L1_SHIFT)
+
+/* The following constants define L2 Mux Peripheral Enables */
+#define XSLCR_MIO_PIN_SRAM_NOR_ENABLE  (0x01 << XSLCR_MIO_L2_SHIFT)
+#define XSLCR_MIO_PIN_NAND_ENABLE      (0x02 << XSLCR_MIO_L2_SHIFT)
+
+/* The following constants define L3 Mux Peripheral Enables */
+#define XSLCR_MIO_PIN_GPIO_ENABLE      (0x00 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_CAN_ENABLE       (0x01 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_IIC_ENABLE       (0x02 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_WDT_ENABLE       (0x03 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_JTAG_ENABLE      (0x03 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_SDIO_ENABLE      (0x04 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_MDIO0_ENABLE     (0x04 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_MDIO1_ENABLE     (0x05 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_SPI_ENABLE       (0x05 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_TTC_ENABLE       (0x06 << XSLCR_MIO_L3_SHIFT)
+#define XSLCR_MIO_PIN_UART_ENABLE      (0x07 << XSLCR_MIO_L3_SHIFT)
+
+/* The following constants define the number of pins associated with each
+ * peripheral */
+#define XSLCR_MIO_NUM_EMAC_PINS                12
+#define XSLCR_MIO_NUM_USB_PINS         12
+#define XSLCR_MIO_NUM_TRACE_DATA2_PINS 04
+#define XSLCR_MIO_NUM_TRACE_DATA4_PINS 06
+#define XSLCR_MIO_NUM_TRACE_DATA8_PINS 10
+#define XSLCR_MIO_NUM_TRACE_DATA16_PINS        18
+#define XSLCR_MIO_NUM_NAND_PINS                (21+1)
+#define XSLCR_MIO_NUM_SMC_A25_PINS     01
+#define XSLCR_MIO_NUM_SMC_CS_PINS      01
+#define XSLCR_MIO_NUM_NAND_CS_PINS     01
+#define XSLCR_MIO_NUM_SRAM_NOR_PINS    38
+#define XSLCR_MIO_NUM_QSPI_PINS                05
+#define XSLCR_MIO_NUM_QSPI_SEL_PINS    01
+#define XSLCR_MIO_NUM_QSPI_FOC_PINS    01
+#define XSLCR_MIO_NUM_GPIO_PINS                01
+#define XSLCR_MIO_NUM_CAN_PINS         02
+#define XSLCR_MIO_NUM_IIC_PINS         02
+#define XSLCR_MIO_NUM_JTAG_PINS                04
+#define XSLCR_MIO_NUM_WDT_PINS         02
+#define XSLCR_MIO_NUM_MDIO_PINS                02
+#define XSLCR_MIO_NUM_SDIO_PINS                06
+#define XSLCR_MIO_NUM_SPI_PINS         06
+#define XSLCR_MIO_NUM_TTC_PINS         02
+#define XSLCR_MIO_NUM_UART_PINS                02
+
+/* The following two constants define the indices of the MIO peripherals EMAC0/1
+ * in the array mio_periph_name */
+#define MIO_EMAC0                      0
+#define MIO_EMAC1                      1
+
+#define XSLCR_MDIO_PIN_0               52
+#define XSLCR_MIO_MAX_PIN              54
+
+#define xslcr_writereg(offset, val)    __raw_writel(val, offset)
+#define xslcr_readreg(offset)          __raw_readl(offset)
+
+
 #define SLCR_PS_RST_CTRL_OFFSET                0x200 /* PS Software Reset Control */
 
 #define SLCR_A9_CPU_CLKSTOP            0x10
 
 void __iomem *zynq_slcr_base;
 
+/**
+ * struct xslcr - slcr device data.
+ * @regs:      baseaddress of device.
+ * @io_lock:   spinlock used for synchronization.
+ *
+ */
+struct xslcr {
+       void __iomem    *regs;
+       spinlock_t      io_lock;
+};
+
+static struct xslcr *slcr;
+
+/**
+ * xslcr_mio - Holds information required to enable/disable a MIO peripheral.
+ *
+ * @set_pins:  Pointer to array of first pins in each pin set for this periph
+ * @max_sets:  Max pin sets for this periph
+ * @numpins:   Number of pins for this periph
+ * @enable_val:        Enable value to assign a MIO pin to this periph
+ */
+struct xslcr_mio {
+       const int *set_pins;
+       int max_sets;
+       int numpins;
+       u32 enable_val;
+};
+
+/**
+ * xslcr_periph_reset - Holds information required to reset a peripheral.
+ *
+ * @reg_offset:        offset of the reset reg for the peripheral
+ * @reset_mask:        mask to reset the peripheral
+ */
+struct xslcr_periph_reset {
+       u32 reg_offset;
+       u32 reset_mask;
+};
+
+/* MIO peripheral names */
+static const char * const mio_periph_name[] = {
+       "emac0",
+       "emac1",
+       "qspi0",
+       "qspi0_sel",
+       "qspi1",
+       "qspi1_sel",
+       "qspi_foc",
+       "trace_data2",
+       "trace_data4",
+       "trace_data8",
+       "trace_data16",
+       "usb0",
+       "usb1",
+       "smc_a25",
+       "smc_cs",
+       "sram_nor",
+       "nand",
+       "nand_cs",
+       "gpio00",
+       "gpio01",
+       "gpio02",
+       "gpio03",
+       "gpio04",
+       "gpio05",
+       "gpio06",
+       "gpio07",
+       "gpio08",
+       "gpio09",
+       "gpio10",
+       "gpio11",
+       "gpio12",
+       "gpio13",
+       "gpio14",
+       "gpio15",
+       "gpio16",
+       "gpio17",
+       "gpio18",
+       "gpio19",
+       "gpio20",
+       "gpio21",
+       "gpio22",
+       "gpio23",
+       "gpio24",
+       "gpio25",
+       "gpio26",
+       "gpio27",
+       "gpio28",
+       "gpio29",
+       "gpio30",
+       "gpio31",
+       "gpio32",
+       "gpio33",
+       "gpio34",
+       "gpio35",
+       "gpio36",
+       "gpio37",
+       "gpio38",
+       "gpio39",
+       "gpio40",
+       "gpio41",
+       "gpio42",
+       "gpio43",
+       "gpio44",
+       "gpio45",
+       "gpio46",
+       "gpio47",
+       "gpio48",
+       "gpio49",
+       "gpio50",
+       "gpio51",
+       "gpio52",
+       "gpio53",
+       "can0",
+       "can1",
+       "iic0",
+       "iic1",
+       "jtag",
+       "wdt",
+       "mdio0",
+       "sdio0",
+       "sdio1",
+       "mdio1",
+       "spi0",
+       "spi1",
+       "ttc0",
+       "ttc1",
+       "uart0",
+       "uart1",
+};
+
+/* Each element in the following array holds the active pinset of a MIO
+ * peripheral. The order of peripherals in this array is same as the order of
+ * peripheral names in the array mio_periph_name */
+static u32 active_pinset[ARRAY_SIZE(mio_periph_name)];
+
+/*
+ * The following arrays contain the first pin in each pin set of a MIO
+ * corresponding peripheral.
+ */
+static const int emac0_pins[] = {
+       16
+};
+
+static const int emac1_pins[] = {
+       28, 40
+};
+
+static const int qspi0_pins[] = {
+       2
+};
+
+static const int qspi0_sel_pins[] = {
+       1
+};
+
+static const int qspi1_pins[] = {
+       9
+};
+
+static const int qspi1_sel_pins[] = {
+       0
+};
+
+static const int qspi_foc_pins[] = {
+       8
+};
+
+static const int trace_data2_pins[] = {
+       12, 24
+};
+
+static const int trace_data4_pins[] = {
+       10, 22
+};
+
+static const int trace_data8_pins[] = {
+       10
+};
+
+static const int trace_data16_pins[] = {
+       2
+};
+
+static const int usb0_pins[] = {
+       28
+};
+
+static const int usb1_pins[] = {
+       40
+};
+
+static const int smc_a25_pins[] = {
+       1
+};
+
+static const int smc_cs_pins[] = {
+       0, 1
+};
+
+static const int sram_nor_pins[] = {
+       2
+};
+
+static const int nand_pins[] = {
+       2
+};
+
+static const int nand_cs_pins[] = {
+       0
+};
+
+static const int gpio00_pins[] = {
+       0
+};
+
+static const int gpio01_pins[] = {
+       1
+};
+
+
+static const int gpio02_pins[] = {
+       2
+};
+
+static const int gpio03_pins[] = {
+       3
+};
+
+static const int gpio04_pins[] = {
+       4
+};
+
+static const int gpio05_pins[] = {
+       5
+};
+
+static const int gpio06_pins[] = {
+       6
+};
+
+static const int gpio07_pins[] = {
+       7
+};
+
+
+static const int gpio08_pins[] = {
+       8
+};
+
+static const int gpio09_pins[] = {
+       9
+};
+
+
+static const int gpio10_pins[] = {
+       10
+};
+
+static const int gpio11_pins[] = {
+       11
+};
+
+static const int gpio12_pins[] = {
+       12
+};
+
+static const int gpio13_pins[] = {
+       13
+};
+
+static const int gpio14_pins[] = {
+       14
+};
+
+
+static const int gpio15_pins[] = {
+       15
+};
+
+static const int gpio16_pins[] = {
+       16
+};
+
+static const int gpio17_pins[] = {
+       17
+};
+
+static const int gpio18_pins[] = {
+       18
+};
+
+static const int gpio19_pins[] = {
+       19
+};
+
+static const int gpio20_pins[] = {
+       20
+};
+
+static const int gpio21_pins[] = {
+       21
+};
+
+
+static const int gpio22_pins[] = {
+       22
+};
+
+static const int gpio23_pins[] = {
+       23
+};
+
+static const int gpio24_pins[] = {
+       24
+};
+
+static const int gpio25_pins[] = {
+       25
+};
+
+static const int gpio26_pins[] = {
+       26
+};
+
+static const int gpio27_pins[] = {
+       27
+};
+
+
+static const int gpio28_pins[] = {
+       28
+};
+
+static const int gpio29_pins[] = {
+       29
+};
+
+
+static const int gpio30_pins[] = {
+       30
+};
+
+static const int gpio31_pins[] = {
+       31
+};
+
+static const int gpio32_pins[] = {
+       32
+};
+
+static const int gpio33_pins[] = {
+       33
+};
+
+static const int gpio34_pins[] = {
+       34
+};
+
+
+static const int gpio35_pins[] = {
+       35
+};
+
+static const int gpio36_pins[] = {
+       36
+};
+
+static const int gpio37_pins[] = {
+       37
+};
+
+static const int gpio38_pins[] = {
+       38
+};
+
+static const int gpio39_pins[] = {
+       39
+};
+
+static const int gpio40_pins[] = {
+       40
+};
+
+static const int gpio41_pins[] = {
+       41
+};
+
+static const int gpio42_pins[] = {
+       42
+};
+
+static const int gpio43_pins[] = {
+       43
+};
+
+static const int gpio44_pins[] = {
+       44
+};
+
+
+static const int gpio45_pins[] = {
+       45
+};
+
+static const int gpio46_pins[] = {
+       46
+};
+
+static const int gpio47_pins[] = {
+       47
+};
+
+static const int gpio48_pins[] = {
+       48
+};
+
+static const int gpio49_pins[] = {
+       49
+};
+
+static const int gpio50_pins[] = {
+       50
+};
+
+static const int gpio51_pins[] = {
+       51
+};
+
+static const int gpio52_pins[] = {
+       52
+};
+
+static const int gpio53_pins[] = {
+       53
+};
+
+static const int can0_pins[] = {
+       10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50
+};
+
+static const int can1_pins[] = {
+       8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52
+};
+
+static const int iic0_pins[] = {
+       10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50
+};
+
+static const int iic1_pins[] = {
+       8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52
+};
+
+static const int jtag0_pins[] = {
+       10, 22, 34, 46
+};
+
+static const int wdt_pins[] = {
+       14, 26, 38, 50, 52
+};
+
+static const int mdio0_pins[] = {
+       52
+};
+
+static const int sdio0_pins[] = {
+       16, 28, 40
+};
+
+static const int sdio1_pins[] = {
+       10, 22, 34, 46
+};
+
+static const int mdio1_pins[] = {
+       52
+};
+
+static const int spi0_pins[] = {
+       16, 28, 40
+};
+
+static const int spi1_pins[] = {
+       10, 22, 34, 46
+};
+
+static const int ttc0_pins[] = {
+       18, 30, 42
+};
+
+static const int ttc1_pins[] = {
+       16, 28, 40
+};
+
+static const int uart0_pins[] = {
+       10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50
+};
+
+static const int uart1_pins[] = {
+       8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52
+};
+
+/* The following array contains required info for enabling MIO peripherals.
+ * The order of the structures in this array is same as the order
+ * of peripheral names in the array mio_periph_name */
+static const struct xslcr_mio mio_periphs[] = {
+       {
+               emac0_pins,
+               ARRAY_SIZE(emac0_pins),
+               XSLCR_MIO_NUM_EMAC_PINS,
+               XSLCR_MIO_PIN_EMAC_ENABLE,
+       },
+       {
+               emac1_pins,
+               ARRAY_SIZE(emac1_pins),
+               XSLCR_MIO_NUM_EMAC_PINS,
+               XSLCR_MIO_PIN_EMAC_ENABLE,
+       },
+       {
+               qspi0_pins,
+               ARRAY_SIZE(qspi0_pins),
+               XSLCR_MIO_NUM_QSPI_PINS,
+               XSLCR_MIO_PIN_QSPI_ENABLE,
+       },
+       {
+               qspi0_sel_pins,
+               ARRAY_SIZE(qspi0_sel_pins),
+               XSLCR_MIO_NUM_QSPI_SEL_PINS,
+               XSLCR_MIO_PIN_QSPI_ENABLE,
+       },
+       {
+               qspi1_pins,
+               ARRAY_SIZE(qspi1_pins),
+               XSLCR_MIO_NUM_QSPI_PINS,
+               XSLCR_MIO_PIN_QSPI_ENABLE,
+       },
+       {
+               qspi1_sel_pins,
+               ARRAY_SIZE(qspi1_sel_pins),
+               XSLCR_MIO_NUM_QSPI_SEL_PINS,
+               XSLCR_MIO_PIN_QSPI_ENABLE,
+       },
+       {       qspi_foc_pins,
+               ARRAY_SIZE(qspi_foc_pins),
+               XSLCR_MIO_NUM_QSPI_FOC_PINS,
+               XSLCR_MIO_PIN_QSPI_ENABLE,
+       },
+       {
+               trace_data2_pins,
+               ARRAY_SIZE(trace_data2_pins),
+               XSLCR_MIO_NUM_TRACE_DATA2_PINS,
+               XSLCR_MIO_PIN_TRACE_PORT_ENABLE,
+       },
+       {
+               trace_data4_pins,
+               ARRAY_SIZE(trace_data4_pins),
+               XSLCR_MIO_NUM_TRACE_DATA4_PINS,
+               XSLCR_MIO_PIN_TRACE_PORT_ENABLE,
+       },
+       {
+               trace_data8_pins,
+               ARRAY_SIZE(trace_data8_pins),
+               XSLCR_MIO_NUM_TRACE_DATA8_PINS,
+               XSLCR_MIO_PIN_TRACE_PORT_ENABLE,
+       },
+       {
+               trace_data16_pins,
+               ARRAY_SIZE(trace_data16_pins),
+               XSLCR_MIO_NUM_TRACE_DATA4_PINS,
+               XSLCR_MIO_PIN_TRACE_PORT_ENABLE,
+       },
+       {
+               usb0_pins,
+               ARRAY_SIZE(usb0_pins),
+               XSLCR_MIO_NUM_USB_PINS,
+               XSLCR_MIO_PIN_USB_ENABLE,
+       },
+       {
+               usb1_pins,
+               ARRAY_SIZE(usb1_pins),
+               XSLCR_MIO_NUM_USB_PINS,
+               XSLCR_MIO_PIN_USB_ENABLE,
+       },
+       {
+               smc_a25_pins,
+               ARRAY_SIZE(smc_a25_pins),
+               XSLCR_MIO_NUM_SMC_A25_PINS,
+               XSLCR_MIO_PIN_SRAM_NOR_ENABLE,
+       },
+       {
+               smc_cs_pins,
+               ARRAY_SIZE(smc_cs_pins),
+               XSLCR_MIO_NUM_SMC_CS_PINS,
+               XSLCR_MIO_PIN_SRAM_NOR_ENABLE,
+       },
+       {
+               sram_nor_pins,
+               ARRAY_SIZE(sram_nor_pins),
+               XSLCR_MIO_NUM_SRAM_NOR_PINS,
+               XSLCR_MIO_PIN_SRAM_NOR_ENABLE,
+       },
+       {
+               nand_pins,
+               ARRAY_SIZE(nand_pins),
+               XSLCR_MIO_NUM_NAND_PINS,
+               XSLCR_MIO_PIN_NAND_ENABLE,
+       },
+       {
+               nand_cs_pins,
+               ARRAY_SIZE(nand_cs_pins),
+               XSLCR_MIO_NUM_NAND_CS_PINS,
+               XSLCR_MIO_PIN_NAND_ENABLE,
+       },
+       {
+               gpio00_pins,
+               ARRAY_SIZE(gpio00_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio01_pins,
+               ARRAY_SIZE(gpio01_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio02_pins,
+               ARRAY_SIZE(gpio02_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio03_pins,
+               ARRAY_SIZE(gpio03_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio04_pins,
+               ARRAY_SIZE(gpio04_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio05_pins,
+               ARRAY_SIZE(gpio05_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio06_pins,
+               ARRAY_SIZE(gpio06_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio07_pins,
+               ARRAY_SIZE(gpio07_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio08_pins,
+               ARRAY_SIZE(gpio08_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio09_pins,
+               ARRAY_SIZE(gpio09_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio10_pins,
+               ARRAY_SIZE(gpio10_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio11_pins,
+               ARRAY_SIZE(gpio11_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio12_pins,
+               ARRAY_SIZE(gpio12_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio13_pins,
+               ARRAY_SIZE(gpio13_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio14_pins,
+               ARRAY_SIZE(gpio14_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio15_pins,
+               ARRAY_SIZE(gpio15_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio16_pins,
+               ARRAY_SIZE(gpio16_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio17_pins,
+               ARRAY_SIZE(gpio17_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio18_pins,
+               ARRAY_SIZE(gpio18_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio19_pins,
+               ARRAY_SIZE(gpio19_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio20_pins,
+               ARRAY_SIZE(gpio20_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio21_pins,
+               ARRAY_SIZE(gpio21_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio22_pins,
+               ARRAY_SIZE(gpio22_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio23_pins,
+               ARRAY_SIZE(gpio23_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio24_pins,
+               ARRAY_SIZE(gpio24_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio25_pins,
+               ARRAY_SIZE(gpio25_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio26_pins,
+               ARRAY_SIZE(gpio26_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio27_pins,
+               ARRAY_SIZE(gpio27_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio28_pins,
+               ARRAY_SIZE(gpio28_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio29_pins,
+               ARRAY_SIZE(gpio29_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio30_pins,
+               ARRAY_SIZE(gpio30_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio31_pins,
+               ARRAY_SIZE(gpio31_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio32_pins,
+               ARRAY_SIZE(gpio32_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio33_pins,
+               ARRAY_SIZE(gpio33_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio34_pins,
+               ARRAY_SIZE(gpio34_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio35_pins,
+               ARRAY_SIZE(gpio35_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio36_pins,
+               ARRAY_SIZE(gpio36_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio37_pins,
+               ARRAY_SIZE(gpio37_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio38_pins,
+               ARRAY_SIZE(gpio38_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio39_pins,
+               ARRAY_SIZE(gpio39_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio40_pins,
+               ARRAY_SIZE(gpio40_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio41_pins,
+               ARRAY_SIZE(gpio41_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio42_pins,
+               ARRAY_SIZE(gpio42_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio43_pins,
+               ARRAY_SIZE(gpio43_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio44_pins,
+               ARRAY_SIZE(gpio44_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio45_pins,
+               ARRAY_SIZE(gpio45_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio46_pins,
+               ARRAY_SIZE(gpio46_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio47_pins,
+               ARRAY_SIZE(gpio47_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio48_pins,
+               ARRAY_SIZE(gpio48_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio49_pins,
+               ARRAY_SIZE(gpio49_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio50_pins,
+               ARRAY_SIZE(gpio50_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio51_pins,
+               ARRAY_SIZE(gpio51_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio52_pins,
+               ARRAY_SIZE(gpio52_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               gpio53_pins,
+               ARRAY_SIZE(gpio53_pins),
+               XSLCR_MIO_NUM_GPIO_PINS,
+               XSLCR_MIO_PIN_GPIO_ENABLE,
+       },
+       {
+               can0_pins,
+               ARRAY_SIZE(can0_pins),
+               XSLCR_MIO_NUM_CAN_PINS,
+               XSLCR_MIO_PIN_CAN_ENABLE,
+       },
+       {
+               can1_pins,
+               ARRAY_SIZE(can1_pins),
+               XSLCR_MIO_NUM_CAN_PINS,
+               XSLCR_MIO_PIN_CAN_ENABLE,
+       },
+       {
+               iic0_pins,
+               ARRAY_SIZE(iic0_pins),
+               XSLCR_MIO_NUM_IIC_PINS,
+               XSLCR_MIO_PIN_IIC_ENABLE,
+       },
+       {
+               iic1_pins,
+               ARRAY_SIZE(iic1_pins),
+               XSLCR_MIO_NUM_IIC_PINS,
+               XSLCR_MIO_PIN_IIC_ENABLE,
+       },
+       {
+               jtag0_pins,
+               ARRAY_SIZE(jtag0_pins),
+               XSLCR_MIO_NUM_JTAG_PINS,
+               XSLCR_MIO_PIN_JTAG_ENABLE,
+       },
+       {
+               wdt_pins,
+               ARRAY_SIZE(wdt_pins),
+               XSLCR_MIO_NUM_WDT_PINS,
+               XSLCR_MIO_PIN_WDT_ENABLE,
+       },
+       {
+               mdio0_pins,
+               ARRAY_SIZE(mdio0_pins),
+               XSLCR_MIO_NUM_MDIO_PINS,
+               XSLCR_MIO_PIN_MDIO0_ENABLE,
+       },
+       {
+               sdio0_pins,
+               ARRAY_SIZE(sdio0_pins),
+               XSLCR_MIO_NUM_SDIO_PINS,
+               XSLCR_MIO_PIN_SDIO_ENABLE,
+       },
+       {
+               sdio1_pins,
+               ARRAY_SIZE(sdio1_pins),
+               XSLCR_MIO_NUM_SDIO_PINS,
+               XSLCR_MIO_PIN_SDIO_ENABLE,
+       },
+       {
+               mdio1_pins,
+               ARRAY_SIZE(mdio1_pins),
+               XSLCR_MIO_NUM_MDIO_PINS,
+               XSLCR_MIO_PIN_MDIO1_ENABLE,
+       },
+       {
+               spi0_pins,
+               ARRAY_SIZE(spi0_pins),
+               XSLCR_MIO_NUM_SPI_PINS,
+               XSLCR_MIO_PIN_SPI_ENABLE,
+       },
+       {
+               spi1_pins,
+               ARRAY_SIZE(spi1_pins),
+               XSLCR_MIO_NUM_SPI_PINS,
+               XSLCR_MIO_PIN_SPI_ENABLE,
+       },
+       {
+               ttc0_pins,
+               ARRAY_SIZE(ttc0_pins),
+               XSLCR_MIO_NUM_TTC_PINS,
+               XSLCR_MIO_PIN_TTC_ENABLE,
+       },
+       {
+               ttc1_pins,
+               ARRAY_SIZE(ttc1_pins),
+               XSLCR_MIO_NUM_TTC_PINS,
+               XSLCR_MIO_PIN_TTC_ENABLE,
+       },
+       {
+               uart0_pins,
+               ARRAY_SIZE(uart0_pins),
+               XSLCR_MIO_NUM_UART_PINS,
+               XSLCR_MIO_PIN_UART_ENABLE,
+       },
+       {
+               uart1_pins,
+               ARRAY_SIZE(uart1_pins),
+               XSLCR_MIO_NUM_UART_PINS,
+               XSLCR_MIO_PIN_UART_ENABLE,
+       },
+};
+
+/*
+ * Each bit in this array is a flag that indicates whether a mio peripheral
+ * is assigned. The order of bits in this array is same as the order of
+ * peripheral names in the array mio_periph_name
+ */
+static u32 periph_status[DIV_ROUND_UP(ARRAY_SIZE(mio_periphs), 32)];
+
+/* Peripherals that can be reset thru SLCR */
+static const char * const reset_periph_name[] = {
+       "pss",
+       "ddr",
+       "sw_amba",
+       "dmac",
+       "usb0_amba",
+       "usb1_amba",
+       "usb0_usb",
+       "usb1_usb",
+       "eth0_mac",
+       "eth1_mac",
+       "eth0_rx",
+       "eth1_rx",
+       "eth0_ref",
+       "eth1_ref",
+       "sdio0_amba",
+       "sdio1_amba",
+       "sdio0_ref",
+       "sdio1_ref",
+       "spi0_amba",
+       "spi1_ambs",
+       "spi0_ref",
+       "spi1_ref",
+       "can0_amba",
+       "can1_amba",
+       "can0_ref",
+       "can1_ref",
+       "iic0_amba",
+       "iic1_amba",
+       "uart0_amba",
+       "uart1_amba",
+       "gpio_amba",
+       "qspi_amba",
+       "qspi_ref",
+       "smc_amba",
+       "smc_ref",
+       "ocm_amba",
+       "pcap2x",
+       "devc_amba",
+       "fpga0_out",
+       "fpga1_out",
+       "fpga2_out",
+       "fpga3_out",
+       "fpga_dma0",
+       "fpga_dma1",
+       "fpga_dma2",
+       "fpga_dma3",
+       "fpga_fmsw0",
+       "fpga_fmsw1",
+       "fpga_fssw0",
+       "fpga_fssw1",
+       "fpga_axds0",
+       "fpga_axds1",
+       "fpga_axds2",
+       "fpga_axds3",
+       "fpga_acp",
+};
+
+/* The following array contains the reset control register offset and the reset
+ * mask for all the peripherals. The order of the structures is same as the
+ * order of peripheral names in the array reset_periph_name */
+static const struct xslcr_periph_reset reset_info[] = {
+       { XSLCR_PSS_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_DDR_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_AMBA_RST_CTRL_OFFSET, 0x00000001 },
+       { XSLCR_DMAC_RST_CTRL_OFFSET, 0x00000001 },
+       { XSLCR_USB_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_USB_RST_CTRL_OFFSET,  0x00000002 },
+       { XSLCR_USB_RST_CTRL_OFFSET,  0x00000010 },
+       { XSLCR_USB_RST_CTRL_OFFSET,  0x00000020 },
+       { XSLCR_EMAC_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_EMAC_RST_CTRL_OFFSET,  0x00000002 },
+       { XSLCR_EMAC_RST_CTRL_OFFSET,  0x00000010 },
+       { XSLCR_EMAC_RST_CTRL_OFFSET,  0x00000020 },
+       { XSLCR_EMAC_RST_CTRL_OFFSET,  0x00000040 },
+       { XSLCR_EMAC_RST_CTRL_OFFSET,  0x00000080 },
+       { XSLCR_SDIO_RST_CTRL_OFFSET, 0x00000001 },
+       { XSLCR_SDIO_RST_CTRL_OFFSET, 0x00000002 },
+       { XSLCR_SDIO_RST_CTRL_OFFSET, 0x00000010 },
+       { XSLCR_SDIO_RST_CTRL_OFFSET, 0x00000020 },
+       { XSLCR_SPI_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_SPI_RST_CTRL_OFFSET,  0x00000002 },
+       { XSLCR_SPI_RST_CTRL_OFFSET,  0x00000004 },
+       { XSLCR_SPI_RST_CTRL_OFFSET,  0x00000008 },
+       { XSLCR_CAN_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_CAN_RST_CTRL_OFFSET,  0x00000002 },
+       { XSLCR_CAN_RST_CTRL_OFFSET,  0x00000004 },
+       { XSLCR_CAN_RST_CTRL_OFFSET,  0x00000008 },
+       { XSLCR_I2C_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_I2C_RST_CTRL_OFFSET,  0x00000002 },
+       { XSLCR_UART_RST_CTRL_OFFSET, 0x00000001 },
+       { XSLCR_UART_RST_CTRL_OFFSET, 0x00000002 },
+       { XSLCR_GPIO_RST_CTRL_OFFSET, 0x00000001 },
+       { XSLCR_QSPI_RST_CTRL_OFFSET, 0x00000001 },
+       { XSLCR_QSPI_RST_CTRL_OFFSET, 0x00000002 },
+       { XSLCR_SMC_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_SMC_RST_CTRL_OFFSET,  0x00000002 },
+       { XSLCR_OCM_RST_CTRL_OFFSET,  0x00000001 },
+       { XSLCR_DEVC_RST_CTRL_OFFSET, 0x00000001 },
+       { XSLCR_DEVC_RST_CTRL_OFFSET, 0x00000002 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000001 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000002 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000004 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000008 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000100 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000200 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000400 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00000800 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00001000 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00002000 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00010000 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00020000 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00100000 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00200000 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00400000 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x00800000 },
+       { XSLCR_FPGA_RST_CTRL_OFFSET, 0x01000000 },
+};
+
 /**
  * zynq_slcr_system_reset - Reset the entire system.
  */
@@ -66,6 +1326,733 @@ void zynq_slcr_system_reset(void)
        writel(1, zynq_slcr_base + SLCR_PS_RST_CTRL_OFFSET);
 }
 
+/**
+ * xslcr_write - Write to a register in SLCR block
+ *
+ * @offset:    Register offset in SLCR block
+ * @val:       Value to write to the register
+ **/
+void xslcr_write(u32 val, u32 offset)
+{
+       xslcr_writereg(slcr->regs + offset, val);
+}
+EXPORT_SYMBOL(xslcr_write);
+
+/**
+ * xslcr_read - Read a register in SLCR block
+ *
+ * @offset:    Register offset in SLCR block
+ *
+ * return:     Value read from the SLCR register
+ **/
+u32 xslcr_read(u32 offset)
+{
+       return xslcr_readreg(slcr->regs + offset);
+}
+EXPORT_SYMBOL(xslcr_read);
+
+/**
+ * xslcr_init_preload_fpga - Disable communication from the PL to PS.
+ */
+void xslcr_init_preload_fpga(void)
+{
+
+       /* Assert FPGA top level output resets */
+       xslcr_write(0xF, XSLCR_FPGA_RST_CTRL_OFFSET);
+
+       /* Disable level shifters */
+       xslcr_write(0, XSLCR_LVL_SHFTR_EN_OFFSET);
+
+       /* Enable output level shifters */
+       xslcr_write(0xA, XSLCR_LVL_SHFTR_EN_OFFSET);
+}
+EXPORT_SYMBOL(xslcr_init_preload_fpga);
+
+/**
+ * xslcr_init_postload_fpga - Re-enable communication from the PL to PS.
+ */
+void xslcr_init_postload_fpga(void)
+{
+
+       /* Enable level shifters */
+       xslcr_write(0xf, XSLCR_LVL_SHFTR_EN_OFFSET);
+
+       /* Deassert AXI interface resets */
+       xslcr_write(0, XSLCR_FPGA_RST_CTRL_OFFSET);
+}
+EXPORT_SYMBOL(xslcr_init_postload_fpga);
+
+/**
+ * xslcr_set_bit - Set a bit
+ *
+ * @data:      Address of the data in which a bit is to be set
+ * @bit:       Bit number to set
+ **/
+static inline void xslcr_set_bit(u32 *data, unsigned int bit)
+{
+       unsigned long mask = 1UL << (bit & 31);
+
+       *(data + (bit >> 5)) |= mask;
+}
+
+/**
+ * xslcr_clear_bit - Clear a bit
+ *
+ * @data:      Address of the data in which a bit is to be cleared
+ * @bit:       Bit number to clear
+ **/
+static inline void xslcr_clear_bit(u32 *data, unsigned int bit)
+{
+       unsigned long mask = 1UL << (bit & 31);
+
+       *(data + (bit >> 5)) &= ~mask;
+}
+
+/**
+ * xslcr_test_bit - Check if a bit is set
+ *
+ * @data:      Address of the data in which a bit is to be checked
+ * @bit:       Bit number to check
+ *
+ * return:     True or false
+ **/
+static inline int xslcr_test_bit(u32 *data, unsigned int bit)
+{
+       unsigned long mask = 1UL << (bit & 31);
+
+       return (*(data + (bit >> 5)) & mask) != 0;
+}
+
+/**
+ * xslcr_mio_isavailable - Check if a MIO pin is available for assignment.
+ *
+ * @pin                MIO pin to be checked.
+ *
+ * return:     -EBUSY if the pin is in use.
+ *             0 if the pin is not assigned.
+ **/
+static int xslcr_mio_isavailable(u32 pin)
+{
+       u32 reg;
+
+       reg = xslcr_readreg(slcr->regs + XSLCR_MIO_PIN_00_OFFSET + (pin * 4));
+       if (reg & XSLCR_MIO_PIN_XX_TRI_ENABLE)
+               return 0;
+
+       return -EBUSY;  /* pin is assigned */
+}
+
+/**
+ * xslcr_enable_mio_peripheral - Enable a MIO peripheral.
+ *
+ * @mio:       id used to lookup the data needed to enable the peripheral.
+ *
+ * This function enables a MIO peripheral on a pinset previously set by the
+ * user, thru sysfs attribute 'pinset'.
+ *
+ * @return     0 if the peripheral is enabled on the given pin set.
+ *             negative error if the peripheral is already enabled, if an
+ *             invalid pinset is specified, or if the pins are assigned to a
+ *             different peripheral.
+ **/
+static int xslcr_enable_mio_peripheral(int mio)
+{
+       const struct xslcr_mio *mio_ptr;
+       unsigned long flags;
+       int pin_set, pin, i;
+
+       /* enable the peripheral only if it hasn't been already enabled */
+       if (xslcr_test_bit(periph_status, mio))
+               return -EBUSY;
+
+       /* get the pin set */
+       pin_set = active_pinset[mio];
+
+       mio_ptr = &mio_periphs[mio];
+       if (pin_set >= mio_ptr->max_sets) {
+               pr_err("%s: Invalid pinset\n", mio_periph_name[mio]);
+               return -EINVAL;
+       }
+
+       /* check whether all the pins in this pin set are unassigned */
+       pin = mio_ptr->set_pins[pin_set]; /* 1st pin */
+       for (i = 0; i < mio_ptr->numpins; i++) {
+               if (xslcr_mio_isavailable(pin + i)) {
+                       pr_err("%s: One or more pins in pinset %d are busy\n",
+                               mio_periph_name[mio], pin_set);
+                       return -EBUSY;
+               }
+       }
+
+       spin_lock_irqsave(&slcr->io_lock, flags);
+       /* assign all pins in the set to this peripheral */
+       for (i = 0; i < mio_ptr->numpins; i++)
+               /* update the MIO register */
+               xslcr_writereg((slcr->regs + ((pin + i) * 4) +
+                               XSLCR_MIO_PIN_00_OFFSET), mio_ptr->enable_val);
+
+       /* mark that the peripheral has been enabled */
+       xslcr_set_bit(periph_status, mio);
+       spin_unlock_irqrestore(&slcr->io_lock, flags);
+
+       pr_debug("Enabled peripheral %s on pinset %d\n",
+                mio_periph_name[mio], pin_set);
+       return 0;
+}
+
+/**
+ * xslcr_disable_mio_peripheral - Disable a MIO peripheral.
+ *
+ * @mio:       id used to lookup the data needed to enable the peripheral.
+ *
+ * This function checks if a MIO peripheral is previously enabled on the pinset
+ * specified by the user, disables the peripheral and releases the MIO pins.
+ *
+ * return:     0 if the peripheral is disabled and MIO pins are released.
+ *             negative error if the peripheral is already disabled, if an
+ *             invalid peripheral is specified, or if the pins are assigned to
+ *             a different peripheral.
+ **/
+static int xslcr_disable_mio_peripheral(int mio)
+{
+       const struct xslcr_mio *mio_ptr;
+       unsigned long flags;
+       int pin_set, pin, i;
+       u32 reg;
+
+       /* disable the peripheral only if it has been already enabled */
+       if (!xslcr_test_bit(periph_status, mio))
+               return -EBUSY;
+
+       /* get the pin set */
+       pin_set = active_pinset[mio];
+
+       mio_ptr = &mio_periphs[mio];
+       if (pin_set >= mio_ptr->max_sets) {
+               pr_err("%s: Invalid pinset %d\n",
+                       mio_periph_name[mio], pin_set);
+               return -EINVAL;
+       }
+
+       pin = mio_ptr->set_pins[pin_set]; /* 1st pin */
+       for (i = 0; i < mio_ptr->numpins; i++) {
+
+               /* check if each pin in the pin_set is assigned to this periph,
+                * to make sure the pins are not being released accidentally*/
+               reg = xslcr_readreg(slcr->regs + XSLCR_MIO_PIN_00_OFFSET +
+                                   (pin * 4));
+               reg &= XSLCR_MIO_LMASK;
+               if (reg != mio_ptr->enable_val) {
+                       pr_err("%s: One or more pins in pinset %d are busy\n",
+                               mio_periph_name[mio], pin_set);
+                       return -EBUSY;
+               }
+       }
+
+       spin_lock_irqsave(&slcr->io_lock, flags);
+       /* release all pins in the set */
+       for (i = 0; i < mio_ptr->numpins; i++) {
+
+               /* update MIO register, set tri-state */
+               xslcr_writereg((slcr->regs + ((pin + i) * 4) +
+                               XSLCR_MIO_PIN_00_OFFSET),
+                               xslcr_readreg((slcr->regs + ((pin + i) * 4) +
+                                       XSLCR_MIO_PIN_00_OFFSET)) |
+                               XSLCR_MIO_PIN_XX_TRI_ENABLE);
+       }
+
+       /* mark that the peripheral has been disabled */
+       xslcr_clear_bit(periph_status, mio);
+       spin_unlock_irqrestore(&slcr->io_lock, flags);
+
+       pr_debug("Disabled peripheral %s on pinset %d\n",
+                mio_periph_name[mio], pin_set);
+       return 0;
+}
+
+/**
+ * xslcr_config_mio_peripheral - Enable/disable a MIO peripheral.
+ *
+ * @dev:       pointer to the MIO device.
+ * @attr:      pointer to the 'enable_pinset' device attribute descriptor.
+ * @buf:       pointer to the buffer with user data.
+ * @size:      size of the buf.
+ *
+ * This function parses the user data in buf and enables/disables the MIO
+ * peripheral specified by dev.
+ *
+ * return:     0 if the peripheral is enabled/disabled successfully.
+ *             negative error if the peripheral configuration failed.
+ **/
+static ssize_t xslcr_config_mio_peripheral(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf, size_t size)
+{
+       unsigned long en;
+       int mio, ret;
+
+       /* get the peripheral */
+       for (mio = 0; mio < ARRAY_SIZE(mio_periph_name); mio++) {
+               if (sysfs_streq(dev_name(dev), mio_periph_name[mio]) == 1)
+                       break;
+       }
+
+       if (mio == ARRAY_SIZE(mio_periph_name)) {
+               dev_err(dev, "Invalid peripheral specified\n");
+               return -EINVAL;
+       }
+
+       ret = kstrtoul(buf, 10, &en);
+       if ((ret) || (en > 1)) {
+               dev_err(dev, "Invalid user argument\n");
+               return -EINVAL;
+       }
+
+       if (en == 1)
+               ret = xslcr_enable_mio_peripheral(mio);
+       else if (en == 0)
+               ret = xslcr_disable_mio_peripheral(mio);
+
+       return size;
+}
+
+static DEVICE_ATTR(enable_pinset, 0222, NULL, xslcr_config_mio_peripheral);
+
+/**
+ * xslcr_store_pinset - Store a pinset for a MIO peripheral.
+ *
+ * @dev:       pointer to the MIO device.
+ * @attr:      pointer to the 'pinset' device attribute descriptor.
+ * @buf:       pointer to the buffer with user data.
+ * @size:      size of the buf.
+ *
+ * This function parses the user data in buf and stores the pinset for the MIO
+ * peripheral specified by dev. This pinset will be later used to enable or
+ * disable the MIO peripheral.
+ *
+ * return:     0 if the peripheral is enabled/disabled successfully.
+ *             negative error if the peripheral configuration failed.
+ **/
+static ssize_t xslcr_store_pinset(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       unsigned long pin_set;
+       int mio, ret;
+
+       /* get the peripheral */
+       for (mio = 0; mio < ARRAY_SIZE(mio_periph_name); mio++) {
+               if (sysfs_streq(dev_name(dev), mio_periph_name[mio]) == 1)
+                       break;
+       }
+
+       if (mio == ARRAY_SIZE(mio_periph_name)) {
+               dev_err(dev, "Invalid peripheral specified\n");
+               return -EINVAL;
+       }
+
+       /* get the pin set */
+       ret = kstrtoul(buf, 10, &pin_set);
+       if ((ret) || (pin_set >= mio_periphs[mio].max_sets)) {
+               dev_err(dev, "Invalid pinset\n");
+               return -EINVAL;
+       }
+
+       /* store the pin set */
+       active_pinset[mio] = pin_set;
+       dev_dbg(dev, "Pinset=%d\n", (unsigned int)pin_set);
+
+       return size;
+}
+
+static DEVICE_ATTR(pinset, 222, NULL, xslcr_store_pinset);
+
+/**
+ * xslcr_get_periph_status - Get the current status of a MIO peripheral.
+ *
+ * @dev:       pointer to this device.
+ * @attr:      pointer to the device attribute descriptor.
+ * @buf:       pointer to the buffer in which pin status is returned as a str.
+ *
+ * This function returns the current status of a MIO peripheral specified by the
+ * user.
+ *
+ * return:     negative error if an invalid peripheral is specified or size of
+ *             the buf, with the status of the peripheral.
+ **/
+static ssize_t xslcr_get_periph_status(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
+{
+       ssize_t size;
+       int mio;
+
+       /* check if a valid peripheral is specified */
+       for (mio = 0; mio < ARRAY_SIZE(mio_periph_name); mio++) {
+               if (sysfs_streq(dev_name(dev), mio_periph_name[mio]) == 1)
+                       break;
+       }
+
+       if (mio == ARRAY_SIZE(mio_periph_name)) {
+               dev_err(dev, "Invalid peripheral specified\n");
+               return -EINVAL;
+       }
+
+       size = sprintf(buf, "%d\n", xslcr_test_bit(periph_status, mio));
+
+       return size;
+}
+
+static DEVICE_ATTR(status, 0444, xslcr_get_periph_status, NULL);
+
+/**
+ * xslcr_reset_periph - Reset a peripheral within PS.
+ *
+ * @dev:       pointer to this device.
+ * @attr:      pointer to the device attribute descriptor.
+ * @buf:       pointer to the buffer with user data.
+ * @size:      size of the buf.
+ *
+ * This function performs a software reset on the peripheral specified by the
+ * user.
+ *
+ * return: negative error if an invalid peripheral is specified or size of the
+ * buf if the peripheral is reset successfully.
+ **/
+static ssize_t xslcr_reset_periph(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       unsigned long flags, rst;
+       int i, ret;
+       u32 reg;
+
+       /* check for a valid peripheral */
+       for (i = 0; i < ARRAY_SIZE(reset_periph_name); i++) {
+               if (sysfs_streq(dev_name(dev), reset_periph_name[i]) == 1)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(reset_periph_name)) {
+               dev_err(dev, "Invalid peripheral specified\n");
+               return -EINVAL;
+       }
+
+       ret = kstrtoul(buf, 10, &rst);
+       if (ret) {
+               dev_err(dev, "Invalid user argument\n");
+               return -EINVAL;
+       }
+
+       /* reset the peripheral */
+       spin_lock_irqsave(&slcr->io_lock, flags);
+
+       /* read the register and modify only the specified bit */
+       reg = xslcr_readreg(slcr->regs + reset_info[i].reg_offset);
+       if (!rst)
+               reg &= ~(reset_info[i].reset_mask);
+       else
+               reg |= reset_info[i].reset_mask;
+
+       xslcr_writereg(slcr->regs + reset_info[i].reg_offset, reg);
+
+       spin_unlock_irqrestore(&slcr->io_lock, flags);
+       return size;
+}
+
+static DEVICE_ATTR(reset, 0222, NULL, xslcr_reset_periph);
+
+/**
+ * show_mio_pin_status - Get the status of all the MIO pins.
+ *
+ * @dev:       pointer to this device.
+ * @attr:      pointer to the device attribute descriptor.
+ * @buf:       pointer to the buffer in which pin status is returned as a str.
+ *
+ * This function returns overall status of the MIO pins as a 64-bit mask. Bit
+ * positions with 1 indicate that the corresponding MIO pin has been assigned to
+ * a peripheral and bit positions with 0 indicate that the pin is free.
+ *
+ * return:     length of the buffer containing the mio pin status.
+ **/
+static ssize_t show_mio_pin_status(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       u64 pin_status = 0;
+       ssize_t status;
+       u32 reg;
+       int i;
+
+       for (i = 0; i < 54; i++) {
+
+               /* read the MIO control register to determine if its free */
+               reg = xslcr_readreg((slcr->regs + (i * 4) +
+                                   XSLCR_MIO_PIN_00_OFFSET));
+               if (!(reg & XSLCR_MIO_PIN_XX_TRI_ENABLE))
+                       xslcr_set_bit((u32 *)&pin_status, i);
+       }
+       status = sprintf(buf, "0x%016Lx\n", pin_status);
+
+       return status;
+}
+
+static DEVICE_ATTR(mio_pin_status, 0444, show_mio_pin_status, NULL);
+
+/* MIO attributes */
+static const struct attribute *xslcr_mio_attrs[] = {
+       &dev_attr_enable_pinset.attr,
+       &dev_attr_pinset.attr,
+       &dev_attr_status.attr,
+       NULL,
+};
+
+static const struct attribute_group xslcr_mio_attr_group = {
+       .attrs = (struct attribute **) xslcr_mio_attrs,
+};
+
+/* MIO class */
+static struct class xslcr_mio_class = {
+       .name =         "xslcr_mio",
+       .owner =        THIS_MODULE,
+};
+
+/* Reset class */
+static struct class xslcr_reset_class = {
+       .name =         "xslcr_reset",
+       .owner =        THIS_MODULE,
+};
+
+/**
+ * match_dev - Match function for finding a device
+ *
+ * @dev:       Device to find.
+ * @data:      Device private data used for finding the device.
+ */
+static int match_dev(struct device *dev, const void *data)
+{
+       return dev_get_drvdata(dev) == data;
+}
+
+/**
+ * xslcr_create_devices - Create devices and their sysfs files.
+ *
+ * @dev:       pointer to the platform device structure.
+ * @xslcr_class:pointer to the class that the devices should be registered to.
+ * @buf:       pointer to the array of device names.
+ * @nr:                number of devices that should be created.
+ *
+ * This function creates devices for MIO peripherals or reset peripherals and
+ * registers them to their respective classes. It also creates sysfs files for
+ * each of these devices.
+ *
+ * return:     0 if all the devices and sysfs files are created successfully.
+ *             negative error if the devices or their sysfs files can't be
+ *             created.
+ **/
+static int xslcr_create_devices(struct platform_device *pdev,
+                               struct class *xslcr_class,
+                               const char * const *periph, int nr)
+{
+       int i, ret;
+
+       for (i = 0; i < nr; i++) {
+               struct device   *dev;
+
+               dev = device_create(xslcr_class, &pdev->dev, MKDEV(0, 0),
+                                   (void *)(periph[i]), periph[i], i);
+               if (!IS_ERR(dev)) {
+                       dev_set_drvdata(dev, (void *)(periph[i]));
+                       if (xslcr_class == &xslcr_mio_class) {
+                               ret = sysfs_create_group(&dev->kobj,
+                                                        &xslcr_mio_attr_group);
+                       } else {
+                               ret = device_create_file(dev, &dev_attr_reset);
+                       }
+
+                       if (ret != 0) {
+                               device_unregister(dev);
+                               dev_err(dev, "Failed to create sysfs attrs\n");
+                               return ret;
+                       }
+               } else
+                       return PTR_ERR(dev);
+       }
+
+       return 0;
+}
+
+/**
+ * xslcr_remove_devices - Remove devices and their sysfs files.
+ *
+ * @dev:       pointer to the platform device structure.
+ * @xslcr_class:pointer to the class that the devices should be registered to.
+ * @buf:       pointer to the array of device names.
+ * @nr:                number of devices that should be created.
+ *
+ * This function removes devices and sysfs files created by xslcr_create_devices
+ * It also unregisters the class to which these devices were registered to.
+ *
+ * return:     0 if all the devices and sysfs files are removed successfully.
+ *             negative error if the devices or their sysfs files can't be
+ *             removed.
+ **/
+static void xslcr_remove_devices(struct class *xslcr_class,
+                                const char * const *periph, int nr)
+{
+       int i;
+
+       for (i = 0; i < nr; i++) {
+               struct device   *dev = NULL;
+
+               dev = class_find_device(xslcr_class, NULL, (const void *)(periph[i]),
+                                       match_dev);
+               if (dev) {
+                       if (xslcr_class == &xslcr_mio_class) {
+                               sysfs_remove_group(&dev->kobj,
+                                                  &xslcr_mio_attr_group);
+                       } else {
+                               device_remove_file(dev, &dev_attr_reset);
+                       }
+                       put_device(dev);
+                       device_unregister(dev);
+               }
+       }
+
+       class_unregister(xslcr_class);
+}
+
+/**
+ * xslcr_get_mio_status - Initialize periph_status
+ *
+ * Read all the MIO control registers and determine which MIO peripherals are
+ * enabled and initialize the global array .
+ **/
+
+static void xslcr_get_mio_status(void)
+{
+       const struct xslcr_mio *mio_ptr;
+       u32 mio_reg;
+       int i, j, k;
+
+       /* num pins */
+       for (i = 0; i < XSLCR_MIO_MAX_PIN;) {
+               mio_reg = xslcr_readreg(slcr->regs + (i * 4) +
+                                       XSLCR_MIO_PIN_00_OFFSET);
+               if (mio_reg & XSLCR_MIO_PIN_XX_TRI_ENABLE) {
+                       i++;
+                       continue;
+               }
+               mio_reg &= XSLCR_MIO_LMASK;
+               /* num periphs */
+               for (j = 0; j < ARRAY_SIZE(mio_periphs); j++) {
+                       if (mio_reg == mio_periphs[j].enable_val) {
+                               mio_ptr = &mio_periphs[j];
+                               for (k = 0; k < mio_ptr->max_sets; k++) {
+                                       if (i == mio_ptr->set_pins[k]) {
+                                               /* mark the periph as enabled */
+                                               xslcr_set_bit(periph_status, j);
+                                               active_pinset[j] = k;
+                                               i += mio_ptr->numpins;
+                                               goto next_periph;
+                                       }
+                               }
+                       }
+               }
+               /* Noone claims this pin */
+               pr_info("MIO pin %2d not assigned(%08x)\n",
+                       i,
+                       xslcr_readreg(slcr->regs + (i * 4) +
+                               XSLCR_MIO_PIN_00_OFFSET)
+                       );
+               i++;
+next_periph:
+               continue;
+       }
+}
+
+/************************Platform Operations*****************************/
+/**
+ * xslcr_probe - Probe call for the device.
+ *
+ * @pdev:      handle to the platform device structure.
+ *
+ * This fucntion allocates resources for the SLCR device and creates sysfs
+ * attributes for the functionality available in the SLCR block. User can
+ * write to these sysfs files to enable/diable mio peripherals/cocks, reset
+ * peripherals, etc.
+ *
+ * Return: 0 on success, negative error otherwise.
+ **/
+static int xslcr_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       spin_lock_init(&slcr->io_lock);
+
+       ret = class_register(&xslcr_mio_class);
+       if (ret < 0)
+               return ret;
+
+       ret = xslcr_create_devices(pdev, &xslcr_mio_class, mio_periph_name,
+                                  ARRAY_SIZE(mio_periph_name));
+       if (ret)
+               goto err_mio_class;
+
+       ret = class_register(&xslcr_reset_class);
+       if (ret < 0)
+               goto err_mio_class;
+
+       ret = xslcr_create_devices(pdev, &xslcr_reset_class, reset_periph_name,
+                                  ARRAY_SIZE(reset_periph_name));
+       if (ret)
+               goto err_rst_class;
+
+       ret = device_create_file(&pdev->dev, &dev_attr_mio_pin_status);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to create sysfs attr\n");
+               goto err_rst_class;
+       }
+
+       platform_set_drvdata(pdev, slcr);
+
+       return 0;
+
+err_rst_class:
+       xslcr_remove_devices(&xslcr_reset_class, reset_periph_name,
+                            ARRAY_SIZE(reset_periph_name));
+err_mio_class:
+       xslcr_remove_devices(&xslcr_mio_class, mio_periph_name,
+                            ARRAY_SIZE(mio_periph_name));
+
+       return ret;
+}
+
+static struct of_device_id slcr_of_match[] = {
+       { .compatible = "xlnx,zynq-slcr", },
+       { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, slcr_of_match);
+
+/* Driver Structure */
+static struct platform_driver xslcr_driver = {
+       .probe          = xslcr_probe,
+       .driver         = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+               .of_match_table = slcr_of_match,
+       },
+};
+
+/**
+ * xslcr_arch_init -  Register the SLCR
+ *
+ * Returns 0 on success, otherwise negative error.
+ */
+static int __init xslcr_arch_init(void)
+{
+       return platform_driver_register(&xslcr_driver);
+}
+module_init(xslcr_arch_init);
+
 /**
  * zynq_slcr_cpu_start - Start cpu
  * @cpu:       cpu number
@@ -112,12 +2099,24 @@ int __init zynq_slcr_init(void)
                BUG();
        }
 
+       slcr = kzalloc(sizeof(*slcr), GFP_KERNEL);
+       if (!slcr) {
+               pr_err("%s: Unable to allocate memory for driver data\n",
+                               __func__);
+               BUG();
+       }
+
+       slcr->regs = zynq_slcr_base;
+
+       /* init periph_status based on the data from MIO control registers */
+       xslcr_get_mio_status();
+
        /* unlock the SLCR so that registers can be changed */
        writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK);
 
        pr_info("%s mapped to %p\n", np->name, zynq_slcr_base);
 
-       xilinx_zynq_clocks_init(zynq_slcr_base);
+       zynq_clock_init(zynq_slcr_base);
 
        of_node_put(np);