From bf4289cba02b8cf770ecd7959ca70839f0dd9d3c Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 29 Dec 2011 14:43:24 +0800 Subject: ATMEL: fix nand ecc support So we can now choose for the board the ecc mode (ecc soft, soft bch, no ecc and hardware). Set ecc mode in the boards to soft as currently in the driver. Move platform data to a common header include/linux/platform_data/atmel_nand.h Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Hans-Christian Egtvedt Acked-by: David Woodhouse --- arch/arm/mach-at91/board-afeb-9260v1.c | 1 + arch/arm/mach-at91/board-cam60.c | 1 + arch/arm/mach-at91/board-cpu9krea.c | 1 + arch/arm/mach-at91/board-dt.c | 1 + arch/arm/mach-at91/board-kb9202.c | 1 + arch/arm/mach-at91/board-neocore926.c | 1 + arch/arm/mach-at91/board-qil-a9260.c | 1 + arch/arm/mach-at91/board-rm9200dk.c | 1 + arch/arm/mach-at91/board-sam9-l9260.c | 1 + arch/arm/mach-at91/board-sam9260ek.c | 1 + arch/arm/mach-at91/board-sam9261ek.c | 1 + arch/arm/mach-at91/board-sam9263ek.c | 1 + arch/arm/mach-at91/board-sam9g20ek.c | 1 + arch/arm/mach-at91/board-sam9m10g45ek.c | 1 + arch/arm/mach-at91/board-sam9rlek.c | 1 + arch/arm/mach-at91/board-snapper9260.c | 1 + arch/arm/mach-at91/board-stamp9g20.c | 1 + arch/arm/mach-at91/board-usb-a926x.c | 1 + arch/arm/mach-at91/board-yl-9200.c | 1 + arch/arm/mach-at91/include/mach/board.h | 15 +-------------- arch/avr32/boards/atngw100/setup.c | 1 + arch/avr32/boards/atstk1000/atstk1002.c | 1 + arch/avr32/mach-at32ap/include/mach/board.h | 13 +------------ drivers/mtd/nand/atmel_nand.c | 25 ++++++------------------- include/linux/platform_data/atmel.h | 26 ++++++++++++++++++++++++++ 25 files changed, 55 insertions(+), 45 deletions(-) create mode 100644 include/linux/platform_data/atmel.h diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c index 3bb40694b02d..161efbaa1029 100644 --- a/arch/arm/mach-at91/board-afeb-9260v1.c +++ b/arch/arm/mach-at91/board-afeb-9260v1.c @@ -138,6 +138,7 @@ static struct atmel_nand_data __initdata afeb9260_nand_data = { .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, .bus_width_16 = 0, + .ecc_mode = NAND_ECC_SOFT, .parts = afeb9260_nand_partition, .num_parts = ARRAY_SIZE(afeb9260_nand_partition), .det_pin = -EINVAL, diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c index 8510e9e54988..c6d44ee0c77e 100644 --- a/arch/arm/mach-at91/board-cam60.c +++ b/arch/arm/mach-at91/board-cam60.c @@ -140,6 +140,7 @@ static struct atmel_nand_data __initdata cam60_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PA9, .enable_pin = AT91_PIN_PA7, + .ecc_mode = NAND_ECC_SOFT, .parts = cam60_nand_partition, .num_parts = ARRAY_SIZE(cam60_nand_partition), }; diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c index 989e1c5a9ca0..5f3680e7c883 100644 --- a/arch/arm/mach-at91/board-cpu9krea.c +++ b/arch/arm/mach-at91/board-cpu9krea.c @@ -117,6 +117,7 @@ static struct atmel_nand_data __initdata cpu9krea_nand_data = { .enable_pin = AT91_PIN_PC14, .bus_width_16 = 0, .det_pin = -EINVAL, + .ecc_mode = NAND_ECC_SOFT, }; #ifdef CONFIG_MACH_CPU9260 diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index 583b72472ad9..e1505fd575e9 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c @@ -47,6 +47,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PC8, .enable_pin = AT91_PIN_PC14, + .ecc_mode = NAND_ECC_SOFT, }; static struct sam9_smc_config __initdata ek_nand_smc_config = { diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c index bb9914582013..59b92aab9bcf 100644 --- a/arch/arm/mach-at91/board-kb9202.c +++ b/arch/arm/mach-at91/board-kb9202.c @@ -108,6 +108,7 @@ static struct atmel_nand_data __initdata kb9202_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PC29, .enable_pin = AT91_PIN_PC28, + .ecc_mode = NAND_ECC_SOFT, .parts = kb9202_nand_partition, .num_parts = ARRAY_SIZE(kb9202_nand_partition), }; diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c index 3f8617c0e04e..57d5f6a4726a 100644 --- a/arch/arm/mach-at91/board-neocore926.c +++ b/arch/arm/mach-at91/board-neocore926.c @@ -190,6 +190,7 @@ static struct atmel_nand_data __initdata neocore926_nand_data = { .rdy_pin = AT91_PIN_PB19, .rdy_pin_active_low = 1, .enable_pin = AT91_PIN_PD15, + .ecc_mode = NAND_ECC_SOFT, .parts = neocore926_nand_partition, .num_parts = ARRAY_SIZE(neocore926_nand_partition), .det_pin = -EINVAL, diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c index e029d220cb84..97907e4fb348 100644 --- a/arch/arm/mach-at91/board-qil-a9260.c +++ b/arch/arm/mach-at91/board-qil-a9260.c @@ -138,6 +138,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c index 9083df04e7ed..d0ec16603788 100644 --- a/arch/arm/mach-at91/board-rm9200dk.c +++ b/arch/arm/mach-at91/board-rm9200dk.c @@ -150,6 +150,7 @@ static struct atmel_nand_data __initdata dk_nand_data = { .det_pin = AT91_PIN_PB1, .rdy_pin = AT91_PIN_PC2, .enable_pin = -EINVAL, + .ecc_mode = NAND_ECC_SOFT, .parts = dk_nand_partition, .num_parts = ARRAY_SIZE(dk_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c index 84bce587735f..e8b116b6cba6 100644 --- a/arch/arm/mach-at91/board-sam9-l9260.c +++ b/arch/arm/mach-at91/board-sam9-l9260.c @@ -139,6 +139,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index be8233bcabdc..3118ab120951 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -181,6 +181,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 40895072a1a7..60cf37b49973 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -187,6 +187,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PC15, .enable_pin = AT91_PIN_PC14, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 29f66052fe63..aeabf850cb80 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -187,6 +187,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PA22, .enable_pin = AT91_PIN_PD15, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index 843d6286c6f4..419e0d5c6d50 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -166,6 +166,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, .det_pin = -EINVAL, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index 57497e2b8878..7b8c647db5f0 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -148,6 +148,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC8, .enable_pin = AT91_PIN_PC14, .det_pin = -EINVAL, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index c1366d0032bf..70a026de2b20 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -94,6 +94,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PD17, .enable_pin = AT91_PIN_PB6, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c index 3c2e3fcc310c..ebc9d01ce742 100644 --- a/arch/arm/mach-at91/board-snapper9260.c +++ b/arch/arm/mach-at91/board-snapper9260.c @@ -110,6 +110,7 @@ static struct atmel_nand_data __initdata snapper9260_nand_data = { .bus_width_16 = 0, .enable_pin = -EINVAL, .det_pin = -EINVAL, + .ecc_mode = NAND_ECC_SOFT, }; static struct sam9_smc_config __initdata snapper9260_nand_smc_config = { diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c index 72eb3b4d9ab6..7640049410a0 100644 --- a/arch/arm/mach-at91/board-stamp9g20.c +++ b/arch/arm/mach-at91/board-stamp9g20.c @@ -86,6 +86,7 @@ static struct atmel_nand_data __initdata nand_data = { .enable_pin = AT91_PIN_PC14, .bus_width_16 = 0, .det_pin = -EINVAL, + .ecc_mode = NAND_ECC_SOFT, }; static struct sam9_smc_config __initdata nand_smc_config = { diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c index 26c36fc2d1e5..cc93152a4da4 100644 --- a/arch/arm/mach-at91/board-usb-a926x.c +++ b/arch/arm/mach-at91/board-usb-a926x.c @@ -198,6 +198,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PA22, .enable_pin = AT91_PIN_PD15, + .ecc_mode = NAND_ECC_SOFT, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c index 52f460768f71..38dd279d30b2 100644 --- a/arch/arm/mach-at91/board-yl-9200.c +++ b/arch/arm/mach-at91/board-yl-9200.c @@ -182,6 +182,7 @@ static struct atmel_nand_data __initdata yl9200_nand_data = { .det_pin = -EINVAL, .rdy_pin = AT91_PIN_PC14, /* R/!B (Sheet10) */ .enable_pin = AT91_PIN_PC15, /* !CE (Sheet10) */ + .ecc_mode = NAND_ECC_SOFT, .parts = yl9200_nand_partition, .num_parts = ARRAY_SIZE(yl9200_nand_partition), }; diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index dc8d6d4f17cf..544a5d5ce416 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -41,6 +41,7 @@ #include #include #include +#include /* USB Device */ struct at91_udc_data { @@ -98,20 +99,6 @@ extern void __init at91_add_device_usbh(struct at91_usbh_data *data); extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data); extern void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data); - /* NAND / SmartMedia */ -struct atmel_nand_data { - int enable_pin; /* chip enable */ - int det_pin; /* card detect */ - int rdy_pin; /* ready/busy */ - u8 rdy_pin_active_low; /* rdy_pin value is inverted */ - u8 ale; /* address line number connected to ALE */ - u8 cle; /* address line number connected to CLE */ - u8 bus_width_16; /* buswidth is 16 bit */ - u8 correction_cap; /* PMECC correction capability */ - u16 sector_size; /* Sector size for PMECC */ - struct mtd_partition *parts; - unsigned int num_parts; -}; extern void __init at91_add_device_nand(struct atmel_nand_data *data); /* I2C*/ diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index 7c756fb189f7..afeae8978a8d 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c @@ -97,6 +97,7 @@ static struct atmel_nand_data atngw100mkii_nand_data __initdata = { .rdy_pin = GPIO_PIN_PB(28), .enable_pin = GPIO_PIN_PE(23), .bus_width_16 = true, + .ecc_mode = NAND_ECC_SOFT, .parts = nand_partitions, .num_parts = ARRAY_SIZE(nand_partitions), }; diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index c56ddac85d61..dc5263321480 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -95,6 +95,7 @@ static struct atmel_nand_data atstk1006_nand_data __initdata = { .ale = 22, .rdy_pin = GPIO_PIN_PB(30), .enable_pin = GPIO_PIN_PB(29), + .ecc_mode = NAND_ECC_SOFT, .parts = nand_partitions, .num_parts = ARRAY_SIZE(num_partitions), }; diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h index 67b111ce332d..71733866cb4f 100644 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ b/arch/avr32/mach-at32ap/include/mach/board.h @@ -7,6 +7,7 @@ #include #include #include +#include #define GPIO_PIN_NONE (-1) @@ -116,18 +117,6 @@ struct platform_device * at32_add_device_cf(unsigned int id, unsigned int extint, struct cf_platform_data *data); -/* NAND / SmartMedia */ -struct atmel_nand_data { - int enable_pin; /* chip enable */ - int det_pin; /* card detect */ - int rdy_pin; /* ready/busy */ - u8 rdy_pin_active_low; /* rdy_pin value is inverted */ - u8 ale; /* address line number connected to ALE */ - u8 cle; /* address line number connected to CLE */ - u8 bus_width_16; /* buswidth is 16 bit */ - struct mtd_partition *parts; - unsigned int num_parts; -}; struct platform_device * at32_add_device_nand(unsigned int id, struct atmel_nand_data *data); diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 35b4fb55dbd6..fb87b03f1a25 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -34,22 +34,10 @@ #include #include #include +#include -#include #include -#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW -#define hard_ecc 1 -#else -#define hard_ecc 0 -#endif - -#ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE -#define no_ecc 1 -#else -#define no_ecc 0 -#endif - static int use_dma = 1; module_param(use_dma, int, 0); @@ -532,23 +520,22 @@ static int __init atmel_nand_probe(struct platform_device *pdev) if (gpio_is_valid(host->board->rdy_pin)) nand_chip->dev_ready = atmel_nand_device_ready; + nand_chip->ecc.mode = host->board->ecc_mode; + regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!regs && hard_ecc) { + if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) { printk(KERN_ERR "atmel_nand: can't get I/O resource " "regs\nFalling back on software ECC\n"); + nand_chip->ecc.mode = NAND_ECC_SOFT; } - nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ - if (no_ecc) - nand_chip->ecc.mode = NAND_ECC_NONE; - if (hard_ecc && regs) { + if (nand_chip->ecc.mode == NAND_ECC_HW) { host->ecc = ioremap(regs->start, resource_size(regs)); if (host->ecc == NULL) { printk(KERN_ERR "atmel_nand: ioremap failed\n"); res = -EIO; goto err_ecc_ioremap; } - nand_chip->ecc.mode = NAND_ECC_HW; nand_chip->ecc.calculate = atmel_nand_calculate; nand_chip->ecc.correct = atmel_nand_correct; nand_chip->ecc.hwctl = atmel_nand_hwctl; diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h new file mode 100644 index 000000000000..7b8a445f2b41 --- /dev/null +++ b/include/linux/platform_data/atmel.h @@ -0,0 +1,26 @@ +/* + * atmel platform data + * + * GPL v2 Only + */ + +#ifndef __ATMEL_NAND_H__ +#define __ATMEL_NAND_H__ + +#include + + /* NAND / SmartMedia */ +struct atmel_nand_data { + int enable_pin; /* chip enable */ + int det_pin; /* card detect */ + int rdy_pin; /* ready/busy */ + u8 rdy_pin_active_low; /* rdy_pin value is inverted */ + u8 ale; /* address line number connected to ALE */ + u8 cle; /* address line number connected to CLE */ + u8 bus_width_16; /* buswidth is 16 bit */ + u8 ecc_mode; /* ecc mode */ + struct mtd_partition *parts; + unsigned int num_parts; +}; + +#endif /* __ATMEL_NAND_H__ */ -- cgit v1.2.3 From 3dcb7ea137c882580d4d421077e9097ef099a3a9 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 29 Dec 2011 14:59:54 +0800 Subject: mtd/atmel_nand: add on_flash_bbt to enable the use of On Flash BBT This will allow to enable it from the board. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: David Woodhouse --- drivers/mtd/nand/atmel_nand.c | 2 +- include/linux/platform_data/atmel.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index fb87b03f1a25..045d174b8277 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -562,7 +562,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) } } - if (on_flash_bbt) { + if (host->board->on_flash_bbt || on_flash_bbt) { printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); nand_chip->bbt_options |= NAND_BBT_USE_FLASH; } diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h index 7b8a445f2b41..d056263545b1 100644 --- a/include/linux/platform_data/atmel.h +++ b/include/linux/platform_data/atmel.h @@ -19,6 +19,7 @@ struct atmel_nand_data { u8 cle; /* address line number connected to CLE */ u8 bus_width_16; /* buswidth is 16 bit */ u8 ecc_mode; /* ecc mode */ + u8 on_flash_bbt; /* bbt on flash */ struct mtd_partition *parts; unsigned int num_parts; }; -- cgit v1.2.3 From 98619dcb77d9dcbed67e39a71e4357fc99dc0f25 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 29 Dec 2011 15:05:50 +0800 Subject: ARM: at91: enable on flash bbt for Atmel Reference and DT boards Enable it on Calao board too as they are in DT too. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/mach-at91/board-dt.c | 1 + arch/arm/mach-at91/board-qil-a9260.c | 1 + arch/arm/mach-at91/board-rm9200dk.c | 1 + arch/arm/mach-at91/board-sam9260ek.c | 1 + arch/arm/mach-at91/board-sam9261ek.c | 1 + arch/arm/mach-at91/board-sam9263ek.c | 1 + arch/arm/mach-at91/board-sam9g20ek.c | 1 + arch/arm/mach-at91/board-sam9m10g45ek.c | 1 + arch/arm/mach-at91/board-sam9rlek.c | 1 + arch/arm/mach-at91/board-usb-a926x.c | 1 + 10 files changed, 10 insertions(+) diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index e1505fd575e9..2eb294b2cc0e 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c @@ -48,6 +48,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC8, .enable_pin = AT91_PIN_PC14, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, }; static struct sam9_smc_config __initdata ek_nand_smc_config = { diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c index 97907e4fb348..b6ed5ed7081a 100644 --- a/arch/arm/mach-at91/board-qil-a9260.c +++ b/arch/arm/mach-at91/board-qil-a9260.c @@ -139,6 +139,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c index d0ec16603788..01332aa538b2 100644 --- a/arch/arm/mach-at91/board-rm9200dk.c +++ b/arch/arm/mach-at91/board-rm9200dk.c @@ -151,6 +151,7 @@ static struct atmel_nand_data __initdata dk_nand_data = { .rdy_pin = AT91_PIN_PC2, .enable_pin = -EINVAL, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = dk_nand_partition, .num_parts = ARRAY_SIZE(dk_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index 3118ab120951..d5aec55b0eb4 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -182,6 +182,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 60cf37b49973..c3f994462864 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -188,6 +188,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC15, .enable_pin = AT91_PIN_PC14, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index aeabf850cb80..66f0ddf4b2ae 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -188,6 +188,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PA22, .enable_pin = AT91_PIN_PD15, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index 419e0d5c6d50..8923ec9f5831 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -167,6 +167,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .enable_pin = AT91_PIN_PC14, .det_pin = -EINVAL, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index 7b8c647db5f0..e1bea73e6b30 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -149,6 +149,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .enable_pin = AT91_PIN_PC14, .det_pin = -EINVAL, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index 70a026de2b20..b109ce2ba864 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -95,6 +95,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PD17, .enable_pin = AT91_PIN_PB6, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c index cc93152a4da4..b7483a3d0980 100644 --- a/arch/arm/mach-at91/board-usb-a926x.c +++ b/arch/arm/mach-at91/board-usb-a926x.c @@ -199,6 +199,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PA22, .enable_pin = AT91_PIN_PD15, .ecc_mode = NAND_ECC_SOFT, + .on_flash_bbt = 1, .parts = ek_nand_partition, .num_parts = ARRAY_SIZE(ek_nand_partition), }; -- cgit v1.2.3 From fa4d34ccd0914ac87336ea2c17e9370dfecef286 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 7 Feb 2012 12:12:51 +0800 Subject: of: introduce helper to manage boolean of_property_read_bool Search for a property in a device node. Returns true if the property exist false otherwise. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Arnd Bergmann Acked-by: Grant Likely --- include/linux/of.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index a75a831e2057..50059cf63135 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -342,6 +342,22 @@ static inline int of_machine_is_compatible(const char *compat) #define of_match_node(_matches, _node) NULL #endif /* CONFIG_OF */ +/** + * of_property_read_bool - Findfrom a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node. + * Returns true if the property exist false otherwise. + */ +static inline bool of_property_read_bool(const struct device_node *np, + const char *propname) +{ + struct property *prop = of_find_property(np, propname, NULL); + + return prop ? true : false; +} + static inline int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) -- cgit v1.2.3 From 770d7c39af940da24dd4c2c048576d778ac0abd4 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sat, 28 Jan 2012 12:12:36 +0800 Subject: of/mtd/nand: add generic bindings and helpers - nand-ecc-mode : String, operation mode of the NAND ecc mode. Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", "soft_bch". - nand-bus-width : 8 or 16 bus width if not present 8 - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Acked-by: Stefan Roese --- Documentation/devicetree/bindings/mtd/nand.txt | 7 +++ drivers/of/Kconfig | 4 ++ drivers/of/Makefile | 1 + drivers/of/of_mtd.c | 85 ++++++++++++++++++++++++++ include/linux/of_mtd.h | 19 ++++++ 5 files changed, 116 insertions(+) create mode 100644 Documentation/devicetree/bindings/mtd/nand.txt create mode 100644 drivers/of/of_mtd.c create mode 100644 include/linux/of_mtd.h diff --git a/Documentation/devicetree/bindings/mtd/nand.txt b/Documentation/devicetree/bindings/mtd/nand.txt new file mode 100644 index 000000000000..03855c8c492a --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/nand.txt @@ -0,0 +1,7 @@ +* MTD generic binding + +- nand-ecc-mode : String, operation mode of the NAND ecc mode. + Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", + "soft_bch". +- nand-bus-width : 8 or 16 bus width if not present 8 +- nand-on-flash-bbt: boolean to enable on flash bbt option if not present false diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 268163dd71c7..fa666a93540c 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -90,4 +90,8 @@ config OF_PCI_IRQ help OpenFirmware PCI IRQ routing helpers +config OF_MTD + depends on MTD + def_bool y + endmenu # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index a73f5a51ff4c..aa90e602c8a7 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_OF_SELFTEST) += selftest.o obj-$(CONFIG_OF_MDIO) += of_mdio.o obj-$(CONFIG_OF_PCI) += of_pci.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o +obj-$(CONFIG_OF_MTD) += of_mtd.o diff --git a/drivers/of/of_mtd.c b/drivers/of/of_mtd.c new file mode 100644 index 000000000000..e7cad627a5d1 --- /dev/null +++ b/drivers/of/of_mtd.c @@ -0,0 +1,85 @@ +/* + * Copyright 2012 Jean-Christophe PLAGNIOL-VILLARD + * + * OF helpers for mtd. + * + * This file is released under the GPLv2 + * + */ +#include +#include +#include +#include + +/** + * It maps 'enum nand_ecc_modes_t' found in include/linux/mtd/nand.h + * into the device tree binding of 'nand-ecc', so that MTD + * device driver can get nand ecc from device tree. + */ +static const char *nand_ecc_modes[] = { + [NAND_ECC_NONE] = "none", + [NAND_ECC_SOFT] = "soft", + [NAND_ECC_HW] = "hw", + [NAND_ECC_HW_SYNDROME] = "hw_syndrome", + [NAND_ECC_HW_OOB_FIRST] = "hw_oob_first", + [NAND_ECC_SOFT_BCH] = "soft_bch", +}; + +/** + * of_get_nand_ecc_mode - Get nand ecc mode for given device_node + * @np: Pointer to the given device_node + * + * The function gets ecc mode string from property 'nand-ecc-mode', + * and return its index in nand_ecc_modes table, or errno in error case. + */ +const int of_get_nand_ecc_mode(struct device_node *np) +{ + const char *pm; + int err, i; + + err = of_property_read_string(np, "nand-ecc-mode", &pm); + if (err < 0) + return err; + + for (i = 0; i < ARRAY_SIZE(nand_ecc_modes); i++) + if (!strcasecmp(pm, nand_ecc_modes[i])) + return i; + + return -ENODEV; +} +EXPORT_SYMBOL_GPL(of_get_nand_ecc_mode); + +/** + * of_get_nand_bus_width - Get nand bus witdh for given device_node + * @np: Pointer to the given device_node + * + * return bus width option, or errno in error case. + */ +int of_get_nand_bus_width(struct device_node *np) +{ + u32 val; + + if (of_property_read_u32(np, "nand-bus-width", &val)) + return 8; + + switch(val) { + case 8: + case 16: + return val; + default: + return -EIO; + } +} +EXPORT_SYMBOL_GPL(of_get_nand_bus_width); + +/** + * of_get_nand_on_flash_bbt - Get nand on flash bbt for given device_node + * @np: Pointer to the given device_node + * + * return true if present false other wise + */ +bool of_get_nand_on_flash_bbt(struct device_node *np) +{ + return of_property_read_bool(np, "nand-on-flash-bbt"); +} +EXPORT_SYMBOL_GPL(of_get_nand_on_flash_bbt); diff --git a/include/linux/of_mtd.h b/include/linux/of_mtd.h new file mode 100644 index 000000000000..bae1b6094c63 --- /dev/null +++ b/include/linux/of_mtd.h @@ -0,0 +1,19 @@ +/* + * Copyright 2012 Jean-Christophe PLAGNIOL-VILLARD + * + * OF helpers for mtd. + * + * This file is released under the GPLv2 + */ + +#ifndef __LINUX_OF_MTD_H +#define __LINUX_OF_NET_H + +#ifdef CONFIG_OF_MTD +#include +extern const int of_get_nand_ecc_mode(struct device_node *np); +int of_get_nand_bus_width(struct device_node *np); +bool of_get_nand_on_flash_bbt(struct device_node *np); +#endif + +#endif /* __LINUX_OF_MTD_H */ -- cgit v1.2.3 From d6a016616ba834b7da7653effb98d413acde7aa2 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 26 Jan 2012 02:11:06 +0800 Subject: atmel/nand: add DT support Use a local copy of board informatin and fill with DT data. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Cc: Nicolas Ferre --- .../devicetree/bindings/mtd/atmel-nand.txt | 41 ++++++++ arch/arm/boot/dts/at91sam9g20.dtsi | 16 +++ arch/arm/boot/dts/at91sam9g45.dtsi | 16 +++ arch/arm/boot/dts/at91sam9m10g45ek.dts | 25 ++++- arch/arm/boot/dts/usb_a9g20.dts | 44 +++++++- arch/arm/mach-at91/at91sam9x5.c | 5 - arch/arm/mach-at91/board-dt.c | 51 ---------- drivers/mtd/nand/atmel_nand.c | 113 +++++++++++++++++---- 8 files changed, 233 insertions(+), 78 deletions(-) create mode 100644 Documentation/devicetree/bindings/mtd/atmel-nand.txt diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt new file mode 100644 index 000000000000..5903ecf6e895 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt @@ -0,0 +1,41 @@ +Atmel NAND flash + +Required properties: +- compatible : "atmel,at91rm9200-nand". +- reg : should specify localbus address and size used for the chip, + and if availlable the ECC. +- atmel,nand-addr-offset : offset for the address latch. +- atmel,nand-cmd-offset : offset for the command latch. +- #address-cells, #size-cells : Must be present if the device has sub-nodes + representing partitions. + +- gpios : specifies the gpio pins to control the NAND device. detect is an + optional gpio and may be set to 0 if not present. + +Optional properties: +- nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default. + Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", + "soft_bch". +- nand-bus-width : 8 or 16 bus width if not present 8 +- nand-on-flash-bbt: boolean to enable on flash bbt option if not present false + +Examples: +nand0: nand@40000000,0 { + compatible = "atmel,at91rm9200-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40000000 0x10000000 + 0xffffe800 0x200 + >; + atmel,nand-addr-offset = <21>; + atmel,nand-cmd-offset = <22>; + nand-on-flash-bbt; + nand-ecc-mode = "soft"; + gpios = <&pioC 13 0 + &pioC 14 0 + 0 + >; + partition@0 { + ... + }; +}; diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index a100db03ec90..4b0dc99b9319 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -172,5 +172,21 @@ status = "disabled"; }; }; + + nand0: nand@40000000 { + compatible = "atmel,at91rm9200-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40000000 0x10000000 + 0xffffe800 0x200 + >; + atmel,nand-addr-offset = <21>; + atmel,nand-cmd-offset = <22>; + gpios = <&pioC 13 0 + &pioC 14 0 + 0 + >; + status = "disabled"; + }; }; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index f779667159b1..d79021b831c4 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -180,5 +180,21 @@ status = "disabled"; }; }; + + nand0: nand@40000000 { + compatible = "atmel,at91rm9200-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40000000 0x10000000 + 0xffffe200 0x200 + >; + atmel,nand-addr-offset = <21>; + atmel,nand-cmd-offset = <22>; + gpios = <&pioC 8 0 + &pioC 14 0 + 0 + >; + status = "disabled"; + }; }; }; diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index 15e25f903cad..fd4531135431 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -14,7 +14,7 @@ compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9"; chosen { - bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2"; + bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2"; }; memory@70000000 { @@ -36,6 +36,29 @@ status = "okay"; }; }; + + nand0: nand@40000000 { + nand-bus-width = <8>; + nand-ecc-mode = "soft"; + nand-on-flash-bbt; + status = "okay"; + + boot@0 { + label = "bootstrap/uboot/kernel"; + reg = <0x0 0x400000>; + }; + + rootfs@400000 { + label = "rootfs"; + reg = <0x400000 0x3C00000>; + }; + + data@4000000 { + label = "data"; + reg = <0x4000000 0xC000000>; + }; + + }; }; leds { diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts index d74545a2a77c..71d83ef316df 100644 --- a/arch/arm/boot/dts/usb_a9g20.dts +++ b/arch/arm/boot/dts/usb_a9g20.dts @@ -13,7 +13,7 @@ compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9"; chosen { - bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs"; + bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs"; }; memory@20000000 { @@ -31,6 +31,48 @@ status = "okay"; }; }; + + nand0: nand@40000000 { + nand-bus-width = <8>; + nand-ecc-mode = "soft"; + nand-on-flash-bbt; + status = "okay"; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x0 0x20000>; + }; + + barebox@20000 { + label = "barebox"; + reg = <0x20000 0x40000>; + }; + + bareboxenv@60000 { + label = "bareboxenv"; + reg = <0x60000 0x20000>; + }; + + bareboxenv2@80000 { + label = "bareboxenv2"; + reg = <0x80000 0x20000>; + }; + + kernel@a0000 { + label = "kernel"; + reg = <0xa0000 0x400000>; + }; + + rootfs@4a0000 { + label = "rootfs"; + reg = <0x4a0000 0x7800000>; + }; + + data@7ca0000 { + label = "data"; + reg = <0x7ca0000 0x8360000>; + }; + }; }; leds { diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index a34d96afa746..7bec5a40d01a 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -313,11 +313,6 @@ void __init at91sam9x5_initialize(void) at91_gpio_init(NULL, 0); } -/* -------------------------------------------------------------------- - * AT91SAM9x5 devices (temporary before modification of code) - * -------------------------------------------------------------------- */ -void __init at91_add_device_nand(struct atmel_nand_data *data) {} - /* -------------------------------------------------------------------- * Interrupt initialization * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index 2eb294b2cc0e..9f729d6c8942 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c @@ -19,10 +19,7 @@ #include #include -#include #include -#include -#include #include #include @@ -30,7 +27,6 @@ #include #include -#include "sam9_smc.h" #include "generic.h" @@ -40,50 +36,6 @@ static void __init ek_init_early(void) at91_initialize(12000000); } -/* det_pin is not connected */ -static struct atmel_nand_data __initdata ek_nand_data = { - .ale = 21, - .cle = 22, - .det_pin = -EINVAL, - .rdy_pin = AT91_PIN_PC8, - .enable_pin = AT91_PIN_PC14, - .ecc_mode = NAND_ECC_SOFT, - .on_flash_bbt = 1, -}; - -static struct sam9_smc_config __initdata ek_nand_smc_config = { - .ncs_read_setup = 0, - .nrd_setup = 2, - .ncs_write_setup = 0, - .nwe_setup = 2, - - .ncs_read_pulse = 4, - .nrd_pulse = 4, - .ncs_write_pulse = 4, - .nwe_pulse = 4, - - .read_cycle = 7, - .write_cycle = 7, - - .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, - .tdf_cycles = 3, -}; - -static void __init ek_add_device_nand(void) -{ - ek_nand_data.bus_width_16 = board_have_nand_16bit(); - /* setup bus-width (8 or 16) */ - if (ek_nand_data.bus_width_16) - ek_nand_smc_config.mode |= AT91_SMC_DBW_16; - else - ek_nand_smc_config.mode |= AT91_SMC_DBW_8; - - /* configure chip-select 3 (NAND) */ - sam9_smc_configure(0, 3, &ek_nand_smc_config); - - at91_add_device_nand(&ek_nand_data); -} - static const struct of_device_id irq_of_match[] __initconst = { { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, @@ -100,9 +52,6 @@ static void __init at91_dt_init_irq(void) static void __init at91_dt_device_init(void) { of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - - /* NAND */ - ek_add_device_nand(); } static const char *at91_dt_board_compat[] __initdata = { diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 045d174b8277..ae7e37d9ac17 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -27,6 +27,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -83,7 +87,7 @@ struct atmel_nand_host { struct mtd_info mtd; void __iomem *io_base; dma_addr_t io_phys; - struct atmel_nand_data *board; + struct atmel_nand_data board; struct device *dev; void __iomem *ecc; @@ -101,8 +105,8 @@ static int cpu_has_dma(void) */ static void atmel_nand_enable(struct atmel_nand_host *host) { - if (gpio_is_valid(host->board->enable_pin)) - gpio_set_value(host->board->enable_pin, 0); + if (gpio_is_valid(host->board.enable_pin)) + gpio_set_value(host->board.enable_pin, 0); } /* @@ -110,8 +114,8 @@ static void atmel_nand_enable(struct atmel_nand_host *host) */ static void atmel_nand_disable(struct atmel_nand_host *host) { - if (gpio_is_valid(host->board->enable_pin)) - gpio_set_value(host->board->enable_pin, 1); + if (gpio_is_valid(host->board.enable_pin)) + gpio_set_value(host->board.enable_pin, 1); } /* @@ -132,9 +136,9 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl return; if (ctrl & NAND_CLE) - writeb(cmd, host->io_base + (1 << host->board->cle)); + writeb(cmd, host->io_base + (1 << host->board.cle)); else - writeb(cmd, host->io_base + (1 << host->board->ale)); + writeb(cmd, host->io_base + (1 << host->board.ale)); } /* @@ -145,8 +149,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) struct nand_chip *nand_chip = mtd->priv; struct atmel_nand_host *host = nand_chip->priv; - return gpio_get_value(host->board->rdy_pin) ^ - !!host->board->rdy_pin_active_low; + return gpio_get_value(host->board.rdy_pin) ^ + !!host->board.rdy_pin_active_low; } /* @@ -261,7 +265,7 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) return; - if (host->board->bus_width_16) + if (host->board.bus_width_16) atmel_read_buf16(mtd, buf, len); else atmel_read_buf8(mtd, buf, len); @@ -277,7 +281,7 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) return; - if (host->board->bus_width_16) + if (host->board.bus_width_16) atmel_write_buf16(mtd, buf, len); else atmel_write_buf8(mtd, buf, len); @@ -469,6 +473,56 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) } } +#if defined(CONFIG_OF) +static int __devinit atmel_of_init_port(struct atmel_nand_host *host, + struct device_node *np) +{ + u32 val; + int ecc_mode; + struct atmel_nand_data *board = &host->board; + enum of_gpio_flags flags; + + if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { + if (val >= 32) { + dev_err(host->dev, "invalid addr-offset %u\n", val); + return -EINVAL; + } + board->ale = val; + } + + if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { + if (val >= 32) { + dev_err(host->dev, "invalid cmd-offset %u\n", val); + return -EINVAL; + } + board->cle = val; + } + + ecc_mode = of_get_nand_ecc_mode(np); + + board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode; + + board->on_flash_bbt = of_get_nand_on_flash_bbt(np); + + if (of_get_nand_bus_width(np) == 16) + board->bus_width_16 = 1; + + board->rdy_pin = of_get_gpio_flags(np, 0, &flags); + board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); + + board->enable_pin = of_get_gpio(np, 1); + board->det_pin = of_get_gpio(np, 2); + + return 0; +} +#else +static int __devinit atmel_of_init_port(struct atmel_nand_host *host, + struct device_node *np) +{ + return -EINVAL; +} +#endif + /* * Probe for the NAND device. */ @@ -479,6 +533,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) struct nand_chip *nand_chip; struct resource *regs; struct resource *mem; + struct mtd_part_parser_data ppdata = {}; int res; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -505,8 +560,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev) mtd = &host->mtd; nand_chip = &host->nand_chip; - host->board = pdev->dev.platform_data; host->dev = &pdev->dev; + if (pdev->dev.of_node) { + res = atmel_of_init_port(host, pdev->dev.of_node); + if (res) + goto err_nand_ioremap; + } else { + memcpy(&host->board, pdev->dev.platform_data, + sizeof(struct atmel_nand_data)); + } nand_chip->priv = host; /* link the private data structures */ mtd->priv = nand_chip; @@ -517,10 +579,10 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->IO_ADDR_W = host->io_base; nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; - if (gpio_is_valid(host->board->rdy_pin)) + if (gpio_is_valid(host->board.rdy_pin)) nand_chip->dev_ready = atmel_nand_device_ready; - nand_chip->ecc.mode = host->board->ecc_mode; + nand_chip->ecc.mode = host->board.ecc_mode; regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) { @@ -545,7 +607,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->chip_delay = 20; /* 20us command delay time */ - if (host->board->bus_width_16) /* 16-bit bus width */ + if (host->board.bus_width_16) /* 16-bit bus width */ nand_chip->options |= NAND_BUSWIDTH_16; nand_chip->read_buf = atmel_read_buf; @@ -554,15 +616,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); atmel_nand_enable(host); - if (gpio_is_valid(host->board->det_pin)) { - if (gpio_get_value(host->board->det_pin)) { + if (gpio_is_valid(host->board.det_pin)) { + if (gpio_get_value(host->board.det_pin)) { printk(KERN_INFO "No SmartMedia card inserted.\n"); res = -ENXIO; goto err_no_card; } } - if (host->board->on_flash_bbt || on_flash_bbt) { + if (host->board.on_flash_bbt || on_flash_bbt) { printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); nand_chip->bbt_options |= NAND_BBT_USE_FLASH; } @@ -637,8 +699,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev) } mtd->name = "atmel_nand"; - res = mtd_device_parse_register(mtd, NULL, 0, - host->board->parts, host->board->num_parts); + ppdata.of_node = pdev->dev.of_node; + res = mtd_device_parse_register(mtd, NULL, &ppdata, + host->board.parts, host->board.num_parts); if (!res) return res; @@ -682,11 +745,21 @@ static int __exit atmel_nand_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_nand_dt_ids[] = { + { .compatible = "atmel,at91rm9200-nand" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids); +#endif + static struct platform_driver atmel_nand_driver = { .remove = __exit_p(atmel_nand_remove), .driver = { .name = "atmel_nand", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_nand_dt_ids), }, }; -- cgit v1.2.3 From 86a89f4ff665d385741a7831c612fc0b9aa22480 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 21 Feb 2012 21:38:18 +0800 Subject: ARM: at91: sam9x5 add nand support Enable the nand in the cpu module with the partition. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/boot/dts/at91sam9g25ek.dts | 2 +- arch/arm/boot/dts/at91sam9x5.dtsi | 15 +++++++++++++++ arch/arm/boot/dts/at91sam9x5cm.dtsi | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts index e64eb932083b..c7596bf26388 100644 --- a/arch/arm/boot/dts/at91sam9g25ek.dts +++ b/arch/arm/boot/dts/at91sam9g25ek.dts @@ -15,7 +15,7 @@ compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9"; chosen { - bootargs = "128M console=ttyS0,115200 mtdparts=atmel_nand:8M(bootstrap/uboot/kernel)ro,-(rootfs) root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"; + bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"; }; ahb { diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index a02e636d8a57..c294657a1f7e 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -172,5 +172,20 @@ status = "disabled"; }; }; + + nand0: nand@40000000 { + compatible = "atmel,at91rm9200-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40000000 0x10000000 + >; + atmel,nand-addr-offset = <21>; + atmel,nand-cmd-offset = <22>; + gpios = <&pioC 8 0 + &pioC 14 0 + 0 + >; + status = "disabled"; + }; }; }; diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi index 64ae3e890259..5b37033bed56 100644 --- a/arch/arm/boot/dts/at91sam9x5cm.dtsi +++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi @@ -12,6 +12,40 @@ reg = <0x20000000 0x8000000>; }; + ahb { + nand0: nand@40000000 { + nand-bus-width = <8>; + nand-ecc-mode = "soft"; + nand-on-flash-bbt; + status = "okay"; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x0 0x40000>; + }; + + uboot@40000 { + label = "u-boot"; + reg = <0x40000 0x80000>; + }; + + ubootenv@c0000 { + label = "U-Boot Env"; + reg = <0xc0000 0x140000>; + }; + + kernel@200000 { + label = "kernel"; + reg = <0x200000 0x600000>; + }; + + rootfs@800000 { + label = "rootfs"; + reg = <0x800000 0x1f800000>; + }; + }; + }; + leds { compatible = "gpio-leds"; -- cgit v1.2.3 From 8ffaa0f40db22564efc44588a9d861d78a1fae02 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 5 Feb 2012 18:22:34 +0800 Subject: i2c/gpio: add DT support To achieve DT support, we need to populate a custom platform_data in a private struct from DT information. To simplify code, the adapter and algorithm are also put into the private struct. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Acked-by: Rob Herring Acked-by: Wolfram Sang Cc: Nicolas Ferre --- .../devicetree/bindings/gpio/gpio_i2c.txt | 32 +++++++ drivers/i2c/busses/i2c-gpio.c | 98 +++++++++++++++++----- 2 files changed, 108 insertions(+), 22 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpio/gpio_i2c.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio_i2c.txt b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt new file mode 100644 index 000000000000..4f8ec947c6bd --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt @@ -0,0 +1,32 @@ +Device-Tree bindings for i2c gpio driver + +Required properties: + - compatible = "i2c-gpio"; + - gpios: sda and scl gpio + + +Optional properties: + - i2c-gpio,sda-open-drain: sda as open drain + - i2c-gpio,scl-open-drain: scl as open drain + - i2c-gpio,scl-output-only: scl as output only + - i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform) + - i2c-gpio,timeout-ms: timeout to get data + +Example nodes: + +i2c@0 { + compatible = "i2c-gpio"; + gpios = <&pioA 23 0 /* sda */ + &pioA 24 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + + rv3029c2@56 { + compatible = "rv3029c2"; + reg = <0x56>; + }; +}; diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index a651779d9ff7..c0330a41db03 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -14,8 +14,15 @@ #include #include #include - -#include +#include +#include +#include + +struct i2c_gpio_private_data { + struct i2c_adapter adap; + struct i2c_algo_bit_data bit_data; + struct i2c_gpio_platform_data pdata; +}; /* Toggle SDA by changing the direction of the pin */ static void i2c_gpio_setsda_dir(void *data, int state) @@ -78,24 +85,62 @@ static int i2c_gpio_getscl(void *data) return gpio_get_value(pdata->scl_pin); } +static int __devinit of_i2c_gpio_probe(struct device_node *np, + struct i2c_gpio_platform_data *pdata) +{ + u32 reg; + + if (of_gpio_count(np) < 2) + return -ENODEV; + + pdata->sda_pin = of_get_gpio(np, 0); + pdata->scl_pin = of_get_gpio(np, 1); + + if (!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) { + pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", + np->full_name, pdata->sda_pin, pdata->scl_pin); + return -ENODEV; + } + + of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay); + + if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®)) + pdata->timeout = msecs_to_jiffies(reg); + + pdata->sda_is_open_drain = + of_property_read_bool(np, "i2c-gpio,sda-open-drain"); + pdata->scl_is_open_drain = + of_property_read_bool(np, "i2c-gpio,scl-open-drain"); + pdata->scl_is_output_only = + of_property_read_bool(np, "i2c-gpio,scl-output-only"); + + return 0; +} + static int __devinit i2c_gpio_probe(struct platform_device *pdev) { + struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; struct i2c_algo_bit_data *bit_data; struct i2c_adapter *adap; int ret; - pdata = pdev->dev.platform_data; - if (!pdata) - return -ENXIO; - - ret = -ENOMEM; - adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (!adap) - goto err_alloc_adap; - bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL); - if (!bit_data) - goto err_alloc_bit_data; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + adap = &priv->adap; + bit_data = &priv->bit_data; + pdata = &priv->pdata; + + if (pdev->dev.of_node) { + ret = of_i2c_gpio_probe(pdev->dev.of_node, pdata); + if (ret) + return ret; + } else { + if (!pdev->dev.platform_data) + return -ENXIO; + memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); + } ret = gpio_request(pdata->sda_pin, "sda"); if (ret) @@ -143,6 +188,7 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) adap->algo_data = bit_data; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; /* * If "dev->id" is negative we consider it as zero. @@ -154,7 +200,9 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) if (ret) goto err_add_bus; - platform_set_drvdata(pdev, adap); + of_i2c_register_devices(adap); + + platform_set_drvdata(pdev, priv); dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", pdata->sda_pin, pdata->scl_pin, @@ -168,34 +216,40 @@ err_add_bus: err_request_scl: gpio_free(pdata->sda_pin); err_request_sda: - kfree(bit_data); -err_alloc_bit_data: - kfree(adap); -err_alloc_adap: return ret; } static int __devexit i2c_gpio_remove(struct platform_device *pdev) { + struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; struct i2c_adapter *adap; - adap = platform_get_drvdata(pdev); - pdata = pdev->dev.platform_data; + priv = platform_get_drvdata(pdev); + adap = &priv->adap; + pdata = &priv->pdata; i2c_del_adapter(adap); gpio_free(pdata->scl_pin); gpio_free(pdata->sda_pin); - kfree(adap->algo_data); - kfree(adap); return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id i2c_gpio_dt_ids[] = { + { .compatible = "i2c-gpio", }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); +#endif + static struct platform_driver i2c_gpio_driver = { .driver = { .name = "i2c-gpio", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(i2c_gpio_dt_ids), }, .probe = i2c_gpio_probe, .remove = __devexit_p(i2c_gpio_remove), -- cgit v1.2.3 From 3b3f8280399c67c592e973193bf3f36a8cab75a0 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 5 Feb 2012 18:25:33 +0800 Subject: ARM: at91: sam9g20 add i2c DT support For now on use i2c-gpio driver on the same pin as the hardware IP. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Acked-by: Rob Herring Cc: Nicolas Ferre --- arch/arm/boot/dts/at91sam9g20.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index 4b0dc99b9319..a885a30d1c82 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -189,4 +189,17 @@ status = "disabled"; }; }; + + i2c@0 { + compatible = "i2c-gpio"; + gpios = <&pioA 23 0 /* sda */ + &pioA 24 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; -- cgit v1.2.3 From b71e1b75d6e22bfed94a2a8879d7f7a30b3e3dde Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 5 Feb 2012 18:31:00 +0800 Subject: ARM: at91: usb_a9g20 add DT i2c support Use i2c-gpio and enable rv3029 RTC. Enable the rtc in the sam9g20 defconfig. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Acked-by: Rob Herring Cc: Nicolas Ferre --- arch/arm/boot/dts/usb_a9g20.dts | 9 +++++++++ arch/arm/configs/at91sam9g20_defconfig | 3 +++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts index 71d83ef316df..0ea90b5be512 100644 --- a/arch/arm/boot/dts/usb_a9g20.dts +++ b/arch/arm/boot/dts/usb_a9g20.dts @@ -97,4 +97,13 @@ gpio-key,wakeup; }; }; + + i2c@0 { + status = "okay"; + + rv3029c2@56 { + compatible = "rv3029c2"; + reg = <0x56>; + }; + }; }; diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig index 9123568d9a8d..994d331b2319 100644 --- a/arch/arm/configs/at91sam9g20_defconfig +++ b/arch/arm/configs/at91sam9g20_defconfig @@ -74,6 +74,8 @@ CONFIG_LEGACY_PTY_COUNT=16 CONFIG_SERIAL_ATMEL=y CONFIG_SERIAL_ATMEL_CONSOLE=y CONFIG_HW_RANDOM=y +CONFIG_I2C=y +CONFIG_I2C_GPIO=y CONFIG_SPI=y CONFIG_SPI_ATMEL=y CONFIG_SPI_SPIDEV=y @@ -105,6 +107,7 @@ CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_RV3029C2=y CONFIG_RTC_DRV_AT91SAM9=y CONFIG_EXT2_FS=y CONFIG_MSDOS_FS=y -- cgit v1.2.3 From 8f24bdaac9547b40f94824bd63c44ead9ea5a211 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 5 Feb 2012 18:32:37 +0800 Subject: ARM: at91: sam9g45 add i2c DT support For now on use i2c-gpio driver on the same pin as the hardware IP. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Acked-by: Rob Herring Cc: Nicolas Ferre --- arch/arm/boot/dts/at91sam9g45.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index d79021b831c4..92fe5a5c0eee 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -197,4 +197,17 @@ status = "disabled"; }; }; + + i2c@0 { + compatible = "i2c-gpio"; + gpios = <&pioA 20 0 /* sda */ + &pioA 21 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <5>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; -- cgit v1.2.3 From 10f71c28b66e6b22e46386c265147eff76e3d7a5 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 23 Feb 2012 22:50:32 +0800 Subject: ARM: at91: sam9x5 add i2c DT support For now on use i2c-gpio driver on the same pin as the hardware IP. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Acked-by: Rob Herring Cc: Nicolas Ferre --- arch/arm/boot/dts/at91sam9x5.dtsi | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index c294657a1f7e..f0104f4e6ab4 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -188,4 +188,43 @@ status = "disabled"; }; }; + + i2c@0 { + compatible = "i2c-gpio"; + gpios = <&pioA 30 0 /* sda */ + &pioA 31 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c@1 { + compatible = "i2c-gpio"; + gpios = <&pioC 0 0 /* sda */ + &pioC 1 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c@2 { + compatible = "i2c-gpio"; + gpios = <&pioB 4 0 /* sda */ + &pioB 5 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; -- cgit v1.2.3 From 8bf7ec6508cdd6e068d42b9acee1ea439543ebe7 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 6 Feb 2012 20:23:21 +0800 Subject: ARM: at91/dt: add Calao DAB-MMX daugther board support for USB-A9G20 http://www.calao-systems.com/articles.php?lng=en&pg=6099 this daughter board add the following device: - Micro-SD socket - TTL 3V3 - (Tx/Rx/RTS/CTS) - I2C port - 0.96" Serial OLED Display Module (over UART) - MP3 decoder with Micro & Speakers - 4x PB, 4x Leds (Blue), 3x Leds (Green, Orange, Red) for now we add only the 2 UARTs, 4 Buttons, 7 leds and i2c via DT used_led1 will not be re-add via DT as it's used by the motherboard too Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi | 96 ++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi diff --git a/arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi b/arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi new file mode 100644 index 000000000000..ad3eca17c436 --- /dev/null +++ b/arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi @@ -0,0 +1,96 @@ +/* + * calao-dab-mmx.dtsi - Device Tree Include file for Calao DAB-MMX Daughter Board + * + * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD + * + * Licensed under GPLv2. + */ + +/ { + ahb { + apb { + usart1: serial@fffb4000 { + status = "okay"; + }; + + usart3: serial@fffd0000 { + status = "okay"; + }; + }; + }; + + i2c-gpio@0 { + status = "okay"; + }; + + leds { + compatible = "gpio-leds"; + + user_led1 { + label = "user_led1"; + gpios = <&pioB 20 1>; + }; + +/* +* led already used by mother board but active as high +* user_led2 { +* label = "user_led2"; +* gpios = <&pioB 21 1>; +* }; +*/ + user_led3 { + label = "user_led3"; + gpios = <&pioB 22 1>; + }; + + user_led4 { + label = "user_led4"; + gpios = <&pioB 23 1>; + }; + + red { + label = "red"; + gpios = <&pioB 24 1>; + }; + + orange { + label = "orange"; + gpios = <&pioB 30 1>; + }; + + green { + label = "green"; + gpios = <&pioB 31 1>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + + user_pb1 { + label = "user_pb1"; + gpios = <&pioB 25 1>; + linux,code = <0x100>; + }; + + user_pb2 { + label = "user_pb2"; + gpios = <&pioB 13 1>; + linux,code = <0x101>; + }; + + user_pb3 { + label = "user_pb3"; + gpios = <&pioA 26 1>; + linux,code = <0x102>; + }; + + user_pb4 { + label = "user_pb4"; + gpios = <&pioC 9 1>; + linux,code = <0x103>; + }; + }; +}; -- cgit v1.2.3 From 2b11ea5bf2fe4b79f9388d2eaf5d84713eb44a4c Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 28 Feb 2012 13:57:51 +0800 Subject: ARM: at91/dt: add specific DT soc init This will allow to have static Device mapping and DT probe mapping for the System Controller. Temporary keep the call to ioremap_registers() until we have the binding for the SDRAM/DDR Controller. Temporary keep the main clock hardcoded to 12MHz until we have the binding for the PMC. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Nicolas Ferre --- arch/arm/mach-at91/board-dt.c | 8 +------- arch/arm/mach-at91/generic.h | 1 + arch/arm/mach-at91/setup.c | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index 9f729d6c8942..c18d4d307801 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c @@ -30,12 +30,6 @@ #include "generic.h" -static void __init ek_init_early(void) -{ - /* Initialize processor: 12.000 MHz crystal */ - at91_initialize(12000000); -} - static const struct of_device_id irq_of_match[] __initconst = { { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, @@ -65,7 +59,7 @@ DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)") /* Maintainer: Atmel */ .timer = &at91sam926x_timer, .map_io = at91_map_io, - .init_early = ek_init_early, + .init_early = at91_dt_initialize, .init_irq = at91_dt_init_irq, .init_machine = at91_dt_device_init, .dt_compat = at91_dt_board_compat, diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 459f01a4a546..d5f5083880f1 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -20,6 +20,7 @@ extern void __init at91_init_sram(int bank, unsigned long base, extern void __init at91rm9200_set_type(int type); extern void __init at91_initialize(unsigned long main_clock); extern void __init at91x40_initialize(unsigned long main_clock); +extern void __init at91_dt_initialize(void); /* Interrupts */ extern void __init at91_init_irq_default(void); diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 372396c2ecb6..c0bd5a625695 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -285,6 +286,23 @@ void __init at91_ioremap_matrix(u32 base_addr) panic("Impossible to ioremap at91_matrix_base\n"); } +#if defined(CONFIG_OF) +void __init at91_dt_initialize(void) +{ + /* temporary until have the ramc binding*/ + at91_boot_soc.ioremap_registers(); + + /* temporary until have the pmc binding */ + /* Init clock subsystem */ + at91_clock_init(12000000); + + /* Register the processor-specific clocks */ + at91_boot_soc.register_clocks(); + + at91_boot_soc.init(); +} +#endif + void __init at91_initialize(unsigned long main_clock) { at91_boot_soc.ioremap_registers(); -- cgit v1.2.3 From eb5e76ffd4e626655944e99bb85b07e17172620d Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Fri, 2 Mar 2012 20:44:23 +0800 Subject: ARM: at91: add pmc DT support Specified the main Oscillator via clock binding. This will allow to do not hardcode it anymore in the DT board at 12MHz. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Nicolas Ferre --- .../devicetree/bindings/arm/atmel-pmc.txt | 11 +++++ arch/arm/boot/dts/at91sam9g20.dtsi | 5 ++ arch/arm/boot/dts/at91sam9g45.dtsi | 5 ++ arch/arm/boot/dts/at91sam9m10g45ek.dts | 11 +++++ arch/arm/boot/dts/at91sam9x5.dtsi | 5 ++ arch/arm/boot/dts/at91sam9x5cm.dtsi | 11 +++++ arch/arm/boot/dts/usb_a9g20.dts | 11 +++++ arch/arm/mach-at91/clock.c | 56 ++++++++++++++++++++-- arch/arm/mach-at91/generic.h | 1 + arch/arm/mach-at91/setup.c | 3 +- 10 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/atmel-pmc.txt diff --git a/Documentation/devicetree/bindings/arm/atmel-pmc.txt b/Documentation/devicetree/bindings/arm/atmel-pmc.txt new file mode 100644 index 000000000000..389bed5056e8 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/atmel-pmc.txt @@ -0,0 +1,11 @@ +* Power Management Controller (PMC) + +Required properties: +- compatible: Should be "atmel,at91rm9200-pmc" +- reg: Should contain PMC registers location and length + +Examples: + pmc: pmc@fffffc00 { + compatible = "atmel,at91rm9200-pmc"; + reg = <0xfffffc00 0x100>; + }; diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index a885a30d1c82..dd5d114a0e1d 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -59,6 +59,11 @@ reg = <0xfffff000 0x200>; }; + pmc: pmc@fffffc00 { + compatible = "atmel,at91rm9200-pmc"; + reg = <0xfffffc00 0x100>; + }; + pit: timer@fffffd30 { compatible = "atmel,at91sam9260-pit"; reg = <0xfffffd30 0xf>; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 92fe5a5c0eee..621a329307d6 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -60,6 +60,11 @@ reg = <0xfffff000 0x200>; }; + pmc: pmc@fffffc00 { + compatible = "atmel,at91rm9200-pmc"; + reg = <0xfffffc00 0x100>; + }; + pit: timer@fffffd30 { compatible = "atmel,at91sam9260-pit"; reg = <0xfffffd30 0xf>; diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index fd4531135431..a8958241f1d7 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -21,6 +21,17 @@ reg = <0x70000000 0x4000000>; }; + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + main_clock: clock@0 { + compatible = "atmel,osc", "fixed-clock"; + clock-frequency = <12000000>; + }; + }; + ahb { apb { dbgu: serial@ffffee00 { diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index f0104f4e6ab4..3855843fc038 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -58,6 +58,11 @@ reg = <0xfffff000 0x200>; }; + pmc: pmc@fffffc00 { + compatible = "atmel,at91rm9200-pmc"; + reg = <0xfffffc00 0x100>; + }; + pit: timer@fffffe30 { compatible = "atmel,at91sam9260-pit"; reg = <0xfffffe30 0xf>; diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi index 5b37033bed56..67936f83c694 100644 --- a/arch/arm/boot/dts/at91sam9x5cm.dtsi +++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi @@ -12,6 +12,17 @@ reg = <0x20000000 0x8000000>; }; + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + main_clock: clock@0 { + compatible = "atmel,osc", "fixed-clock"; + clock-frequency = <12000000>; + }; + }; + ahb { nand0: nand@40000000 { nand-bus-width = <8>; diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts index 0ea90b5be512..73f1dc48f307 100644 --- a/arch/arm/boot/dts/usb_a9g20.dts +++ b/arch/arm/boot/dts/usb_a9g20.dts @@ -20,6 +20,17 @@ reg = <0x20000000 0x4000000>; }; + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + main_clock: clock@0 { + compatible = "atmel,osc", "fixed-clock"; + clock-frequency = <12000000>; + }; + }; + ahb { apb { dbgu: serial@fffff200 { diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index be51ca7f694d..a0f4d7424cdc 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -671,16 +672,12 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock) uhpck.rate_hz /= 1 + ((at91_pmc_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8); } -int __init at91_clock_init(unsigned long main_clock) +static int __init at91_pmc_init(unsigned long main_clock) { unsigned tmp, freq, mckr; int i; int pll_overclock = false; - at91_pmc_base = ioremap(AT91_PMC, 256); - if (!at91_pmc_base) - panic("Impossible to ioremap AT91_PMC 0x%x\n", AT91_PMC); - /* * When the bootloader initialized the main oscillator correctly, * there's no problem using the cycle counter. But if it didn't, @@ -802,6 +799,55 @@ int __init at91_clock_init(unsigned long main_clock) return 0; } +#if defined(CONFIG_OF) +static struct of_device_id pmc_ids[] = { + { .compatible = "atmel,at91rm9200-pmc" }, + { /*sentinel*/ } +}; + +static struct of_device_id osc_ids[] = { + { .compatible = "atmel,osc" }, + { /*sentinel*/ } +}; + +int __init at91_dt_clock_init(void) +{ + struct device_node *np; + u32 main_clock = 0; + + np = of_find_matching_node(NULL, pmc_ids); + if (!np) + panic("unable to find compatible pmc node in dtb\n"); + + at91_pmc_base = of_iomap(np, 0); + if (!at91_pmc_base) + panic("unable to map pmc cpu registers\n"); + + of_node_put(np); + + /* retrieve the freqency of fixed clocks from device tree */ + np = of_find_matching_node(NULL, osc_ids); + if (np) { + u32 rate; + if (!of_property_read_u32(np, "clock-frequency", &rate)) + main_clock = rate; + } + + of_node_put(np); + + return at91_pmc_init(main_clock); +} +#endif + +int __init at91_clock_init(unsigned long main_clock) +{ + at91_pmc_base = ioremap(AT91_PMC, 256); + if (!at91_pmc_base) + panic("Impossible to ioremap AT91_PMC 0x%x\n", AT91_PMC); + + return at91_pmc_init(main_clock); +} + /* * Several unused clocks may be active. Turn them off. */ diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index d5f5083880f1..dd9b346c451d 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -53,6 +53,7 @@ extern void __init at91sam9rl_set_console_clock(int id); extern void __init at91sam9g45_set_console_clock(int id); #ifdef CONFIG_AT91_PMC_UNIT extern int __init at91_clock_init(unsigned long main_clock); +extern int __init at91_dt_clock_init(void); #else static int inline at91_clock_init(unsigned long main_clock) { return 0; } #endif diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index c0bd5a625695..d7abc25f6c64 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -292,9 +292,8 @@ void __init at91_dt_initialize(void) /* temporary until have the ramc binding*/ at91_boot_soc.ioremap_registers(); - /* temporary until have the pmc binding */ /* Init clock subsystem */ - at91_clock_init(12000000); + at91_dt_clock_init(); /* Register the processor-specific clocks */ at91_boot_soc.register_clocks(); -- cgit v1.2.3 From 21ea52aadd6296480baad3b04fef87230517b54c Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sat, 3 Mar 2012 03:14:16 +0800 Subject: ARM: at91: always enable sam9 restart This is need for multiple SoC in the same kernel image and DT. As we will chose the restart function via binding. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Nicolas Ferre --- arch/arm/mach-at91/Kconfig | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index e55cdcbd81fb..45db05d8d94c 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -20,9 +20,11 @@ config HAVE_AT91_USART5 config AT91_SAM9_ALT_RESET bool + default !ARCH_AT91X40 config AT91_SAM9G45_RESET bool + default !ARCH_AT91X40 menu "Atmel AT91 System-on-Chip" @@ -45,7 +47,6 @@ config ARCH_AT91SAM9260 select HAVE_AT91_USART4 select HAVE_AT91_USART5 select HAVE_NET_MACB - select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9261 bool "AT91SAM9261" @@ -53,7 +54,6 @@ config ARCH_AT91SAM9261 select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL select HAVE_AT91_DBGU0 - select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9G10 bool "AT91SAM9G10" @@ -61,7 +61,6 @@ config ARCH_AT91SAM9G10 select GENERIC_CLOCKEVENTS select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL - select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9263 bool "AT91SAM9263" @@ -70,7 +69,6 @@ config ARCH_AT91SAM9263 select HAVE_FB_ATMEL select HAVE_NET_MACB select HAVE_AT91_DBGU1 - select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9RL bool "AT91SAM9RL" @@ -79,7 +77,6 @@ config ARCH_AT91SAM9RL select HAVE_AT91_USART3 select HAVE_FB_ATMEL select HAVE_AT91_DBGU0 - select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9G20 bool "AT91SAM9G20" @@ -90,7 +87,6 @@ config ARCH_AT91SAM9G20 select HAVE_AT91_USART4 select HAVE_AT91_USART5 select HAVE_NET_MACB - select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9G45 bool "AT91SAM9G45" @@ -100,7 +96,6 @@ config ARCH_AT91SAM9G45 select HAVE_FB_ATMEL select HAVE_NET_MACB select HAVE_AT91_DBGU1 - select AT91_SAM9G45_RESET config ARCH_AT91SAM9X5 bool "AT91SAM9x5 family" @@ -109,7 +104,6 @@ config ARCH_AT91SAM9X5 select HAVE_FB_ATMEL select HAVE_NET_MACB select HAVE_AT91_DBGU0 - select AT91_SAM9G45_RESET config ARCH_AT91X40 bool "AT91x40" -- cgit v1.2.3 From c8082d344ac4c05932fec1766e5e9ce72cf286ed Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sat, 3 Mar 2012 03:16:27 +0800 Subject: ARM: at91: add RSTC (Reset Controller) dt support Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Nicolas Ferre --- .../devicetree/bindings/arm/atmel-at91.txt | 12 +++++++++ arch/arm/boot/dts/at91sam9g20.dtsi | 5 ++++ arch/arm/boot/dts/at91sam9g45.dtsi | 5 ++++ arch/arm/boot/dts/at91sam9x5.dtsi | 5 ++++ arch/arm/mach-at91/at91sam9x5.c | 1 - arch/arm/mach-at91/setup.c | 30 ++++++++++++++++++++++ 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 1aeaf6f2a1ba..a64f86717b5d 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -30,3 +30,15 @@ One interrupt per TC channel in a TC block: reg = <0xfffdc000 0x100>; interrupts = <26 4 27 4 28 4>; }; + +RSTC Reset Controller required properties: +- compatible: Should be "atmel,-rstc". + can be "at91sam9260" or "at91sam9g45" +- reg: Should contain registers location and length + +Example: + + rstc@fffffd00 { + compatible = "atmel,at91sam9260-rstc"; + reg = <0xfffffd00 0x10>; + }; diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index dd5d114a0e1d..bcad6e7dccce 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -64,6 +64,11 @@ reg = <0xfffffc00 0x100>; }; + rstc@fffffd00 { + compatible = "atmel,at91sam9260-rstc"; + reg = <0xfffffd00 0x10>; + }; + pit: timer@fffffd30 { compatible = "atmel,at91sam9260-pit"; reg = <0xfffffd30 0xf>; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 621a329307d6..faccd4f5aace 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -65,6 +65,11 @@ reg = <0xfffffc00 0x100>; }; + rstc@fffffd00 { + compatible = "atmel,at91sam9g45-rstc"; + reg = <0xfffffd00 0x10>; + }; + pit: timer@fffffd30 { compatible = "atmel,at91sam9260-pit"; reg = <0xfffffd30 0xf>; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 3855843fc038..d9a93fdd35a5 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -63,6 +63,11 @@ reg = <0xfffffc00 0x100>; }; + rstc@fffffe00 { + compatible = "atmel,at91sam9g45-rstc"; + reg = <0xfffffe00 0x10>; + }; + pit: timer@fffffe30 { compatible = "atmel,at91sam9260-pit"; reg = <0xfffffe30 0xf>; diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index 7bec5a40d01a..c121fe5fabbd 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -306,7 +306,6 @@ static void __init at91sam9x5_ioremap_registers(void) void __init at91sam9x5_initialize(void) { - arm_pm_restart = at91sam9g45_restart; at91_extern_irq = (1 << AT91SAM9X5_ID_IRQ0); /* Register GPIO subsystem (using DT) */ diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index d7abc25f6c64..3e48b59dfa74 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -287,8 +287,38 @@ void __init at91_ioremap_matrix(u32 base_addr) } #if defined(CONFIG_OF) +static struct of_device_id rstc_ids[] = { + { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_alt_restart }, + { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart }, + { /*sentinel*/ } +}; + +static void at91_dt_rstc(void) +{ + struct device_node *np; + const struct of_device_id *of_id; + + np = of_find_matching_node(NULL, rstc_ids); + if (!np) + panic("unable to find compatible rstc node in dtb\n"); + + at91_rstc_base = of_iomap(np, 0); + if (!at91_rstc_base) + panic("unable to map rstc cpu registers\n"); + + of_id = of_match_node(rstc_ids, np); + if (!of_id) + panic("AT91: rtsc no restart function availlable\n"); + + arm_pm_restart = of_id->data; + + of_node_put(np); +} + void __init at91_dt_initialize(void) { + at91_dt_rstc(); + /* temporary until have the ramc binding*/ at91_boot_soc.ioremap_registers(); -- cgit v1.2.3 From a7776ec625c8ca90d050953946a5b72eaf41c21c Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Fri, 2 Mar 2012 20:54:37 +0800 Subject: ARM: at91: add ram controller DT support We can now drop the call to ioremap_registers() as we have the binding for the SDRAM/DDR Controller. Drop ioremap_registers() for sam9x5 too. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Nicolas Ferre --- .../devicetree/bindings/arm/atmel-at91.txt | 19 ++++++++++ arch/arm/boot/dts/at91sam9g20.dtsi | 5 +++ arch/arm/boot/dts/at91sam9g45.dtsi | 6 ++++ arch/arm/boot/dts/at91sam9x5.dtsi | 5 +++ arch/arm/mach-at91/at91sam9x5.c | 6 ---- arch/arm/mach-at91/include/mach/at91sam9x5.h | 5 --- arch/arm/mach-at91/pm.c | 13 ------- arch/arm/mach-at91/setup.c | 40 ++++++++++++++++++++-- 8 files changed, 72 insertions(+), 27 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index a64f86717b5d..1f8782077433 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -42,3 +42,22 @@ Example: compatible = "atmel,at91sam9260-rstc"; reg = <0xfffffd00 0x10>; }; + +RAMC SDRAM/DDR Controller required properties: +- compatible: Should be "atmel,at91sam9260-sdramc", + "atmel,at91sam9g45-ddramc", +- reg: Should contain registers location and length + For at91sam9263 and at91sam9g45 you must specify 2 entries. + +Examples: + + ramc0: ramc@ffffe800 { + compatible = "atmel,at91sam9g45-ddramc"; + reg = <0xffffe800 0x200>; + }; + + ramc0: ramc@ffffe400 { + compatible = "atmel,at91sam9g45-ddramc"; + reg = <0xffffe400 0x200 + 0xffffe600 0x200>; + }; diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index bcad6e7dccce..0a1df8d9bfb6 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -59,6 +59,11 @@ reg = <0xfffff000 0x200>; }; + ramc0: ramc@ffffea00 { + compatible = "atmel,at91sam9260-sdramc"; + reg = <0xffffea00 0x200>; + }; + pmc: pmc@fffffc00 { compatible = "atmel,at91rm9200-pmc"; reg = <0xfffffc00 0x100>; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index faccd4f5aace..587a1913c062 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -60,6 +60,12 @@ reg = <0xfffff000 0x200>; }; + ramc0: ramc@ffffe400 { + compatible = "atmel,at91sam9g45-ddramc"; + reg = <0xffffe400 0x200 + 0xffffe600 0x200>; + }; + pmc: pmc@fffffc00 { compatible = "atmel,at91rm9200-pmc"; reg = <0xfffffc00 0x100>; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index d9a93fdd35a5..73c46e3dffab 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -58,6 +58,11 @@ reg = <0xfffff000 0x200>; }; + ramc0: ramc@ffffe800 { + compatible = "atmel,at91sam9g45-ddramc"; + reg = <0xffffe800 0x200>; + }; + pmc: pmc@fffffc00 { compatible = "atmel,at91rm9200-pmc"; reg = <0xfffffc00 0x100>; diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index c121fe5fabbd..01b2bd816a9a 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -299,11 +299,6 @@ static void __init at91sam9x5_map_io(void) at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE); } -static void __init at91sam9x5_ioremap_registers(void) -{ - at91_ioremap_ramc(0, AT91SAM9X5_BASE_DDRSDRC0, 512); -} - void __init at91sam9x5_initialize(void) { at91_extern_irq = (1 << AT91SAM9X5_ID_IRQ0); @@ -356,7 +351,6 @@ static unsigned int at91sam9x5_default_irq_priority[NR_AIC_IRQS] __initdata = { struct at91_init_soc __initdata at91sam9x5_soc = { .map_io = at91sam9x5_map_io, .default_irq_priority = at91sam9x5_default_irq_priority, - .ioremap_registers = at91sam9x5_ioremap_registers, .register_clocks = at91sam9x5_register_clocks, .init = at91sam9x5_initialize, }; diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h b/arch/arm/mach-at91/include/mach/at91sam9x5.h index a297a77d88e2..88e43d534cdf 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9x5.h +++ b/arch/arm/mach-at91/include/mach/at91sam9x5.h @@ -54,11 +54,6 @@ #define AT91SAM9X5_BASE_USART1 0xf8020000 #define AT91SAM9X5_BASE_USART2 0xf8024000 -/* - * System Peripherals - */ -#define AT91SAM9X5_BASE_DDRSDRC0 0xffffe800 - /* * Base addresses for early serial code (uncompress.h) */ diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 6c9d5e69ac28..f630250c6b87 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -197,19 +197,6 @@ extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0, extern u32 at91_slow_clock_sz; #endif -void __iomem *at91_ramc_base[2]; - -void __init at91_ioremap_ramc(int id, u32 addr, u32 size) -{ - if (id < 0 || id > 1) { - pr_emerg("Wrong RAM controller id (%d), cannot continue\n", id); - BUG(); - } - at91_ramc_base[id] = ioremap(addr, size); - if (!at91_ramc_base[id]) - panic("Impossible to ioremap ramc.%d 0x%x\n", id, addr); -} - static int at91_pm_enter(suspend_state_t state) { at91_gpio_suspend(); diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 3e48b59dfa74..46d0a56ba825 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -52,6 +52,19 @@ void __init at91_init_interrupts(unsigned int *priority) at91_gpio_irq_setup(); } +void __iomem *at91_ramc_base[2]; + +void __init at91_ioremap_ramc(int id, u32 addr, u32 size) +{ + if (id < 0 || id > 1) { + pr_emerg("Wrong RAM controller id (%d), cannot continue\n", id); + BUG(); + } + at91_ramc_base[id] = ioremap(addr, size); + if (!at91_ramc_base[id]) + panic("Impossible to ioremap ramc.%d 0x%x\n", id, addr); +} + static struct map_desc sram_desc[2] __initdata; void __init at91_init_sram(int bank, unsigned long base, unsigned int length) @@ -315,12 +328,33 @@ static void at91_dt_rstc(void) of_node_put(np); } +static struct of_device_id ramc_ids[] = { + { .compatible = "atmel,at91sam9260-sdramc" }, + { .compatible = "atmel,at91sam9g45-ddramc" }, + { /*sentinel*/ } +}; + +static void at91_dt_ramc(void) +{ + struct device_node *np; + + np = of_find_matching_node(NULL, ramc_ids); + if (!np) + panic("unable to find compatible ram conroller node in dtb\n"); + + at91_ramc_base[0] = of_iomap(np, 0); + if (!at91_ramc_base[0]) + panic("unable to map ramc[0] cpu registers\n"); + /* the controller may have 2 banks */ + at91_ramc_base[1] = of_iomap(np, 1); + + of_node_put(np); +} + void __init at91_dt_initialize(void) { at91_dt_rstc(); - - /* temporary until have the ramc binding*/ - at91_boot_soc.ioremap_registers(); + at91_dt_ramc(); /* Init clock subsystem */ at91_dt_clock_init(); -- cgit v1.2.3 From 82015c4eae2ac67cfed8e98f8d9a4ee77a2d26ca Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Fri, 2 Mar 2012 21:01:00 +0800 Subject: ARM: at91: add Shutdown Controller (SHDWC) DT support Use a string to specific the wakeup mode to make it more readable. Add the Real-time Clock Wake-up support too for sam9g45 and sam9x5. Add AT91_SHDW_CPTWK0_MAX to specific the Max of the Wakeup Counter. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Nicolas Ferre --- .../devicetree/bindings/arm/atmel-at91.txt | 29 ++++++++ arch/arm/boot/dts/at91sam9g20.dtsi | 5 ++ arch/arm/boot/dts/at91sam9g45.dtsi | 5 ++ arch/arm/boot/dts/at91sam9x5.dtsi | 5 ++ arch/arm/mach-at91/include/mach/at91_shdwc.h | 4 +- arch/arm/mach-at91/setup.c | 77 ++++++++++++++++++++++ 6 files changed, 124 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 1f8782077433..ecc81e368715 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -61,3 +61,32 @@ Examples: reg = <0xffffe400 0x200 0xffffe600 0x200>; }; + +SHDWC Shutdown Controller + +required properties: +- compatible: Should be "atmel,-shdwc". + can be "at91sam9260", "at91sam9rl" or "at91sam9x5". +- reg: Should contain registers location and length + +optional properties: +- atmel,wakeup-mode: String, operation mode of the wakeup mode. + Supported values are: "none", "high", "low", "any". +- atmel,wakeup-counter: Counter on Wake-up 0 (between 0x0 and 0xf). + +optional at91sam9260 properties: +- atmel,wakeup-rtt-timer: boolean to enable Real-time Timer Wake-up. + +optional at91sam9rl properties: +- atmel,wakeup-rtc-timer: boolean to enable Real-time Clock Wake-up. +- atmel,wakeup-rtt-timer: boolean to enable Real-time Timer Wake-up. + +optional at91sam9x5 properties: +- atmel,wakeup-rtc-timer: boolean to enable Real-time Clock Wake-up. + +Example: + + rstc@fffffd00 { + compatible = "atmel,at91sam9260-rstc"; + reg = <0xfffffd00 0x10>; + }; diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index 0a1df8d9bfb6..9a0647bb387f 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -74,6 +74,11 @@ reg = <0xfffffd00 0x10>; }; + shdwc@fffffd10 { + compatible = "atmel,at91sam9260-shdwc"; + reg = <0xfffffd10 0x10>; + }; + pit: timer@fffffd30 { compatible = "atmel,at91sam9260-pit"; reg = <0xfffffd30 0xf>; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 587a1913c062..8908f078c307 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -83,6 +83,11 @@ }; + shdwc@fffffd10 { + compatible = "atmel,at91sam9rl-shdwc"; + reg = <0xfffffd10 0x10>; + }; + tcb0: timer@fff7c000 { compatible = "atmel,at91rm9200-tcb"; reg = <0xfff7c000 0x100>; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 73c46e3dffab..20155ccbbe14 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -73,6 +73,11 @@ reg = <0xfffffe00 0x10>; }; + shdwc@fffffe10 { + compatible = "atmel,at91sam9x5-shdwc"; + reg = <0xfffffe10 0x10>; + }; + pit: timer@fffffe30 { compatible = "atmel,at91sam9260-pit"; reg = <0xfffffe30 0xf>; diff --git a/arch/arm/mach-at91/include/mach/at91_shdwc.h b/arch/arm/mach-at91/include/mach/at91_shdwc.h index 1d4fe822c77a..60478ea8bd46 100644 --- a/arch/arm/mach-at91/include/mach/at91_shdwc.h +++ b/arch/arm/mach-at91/include/mach/at91_shdwc.h @@ -36,9 +36,11 @@ extern void __iomem *at91_shdwc_base; #define AT91_SHDW_WKMODE0_HIGH 1 #define AT91_SHDW_WKMODE0_LOW 2 #define AT91_SHDW_WKMODE0_ANYLEVEL 3 -#define AT91_SHDW_CPTWK0 (0xf << 4) /* Counter On Wake Up 0 */ +#define AT91_SHDW_CPTWK0_MAX 0xf /* Maximum Counter On Wake Up 0 */ +#define AT91_SHDW_CPTWK0 (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */ #define AT91_SHDW_CPTWK0_(x) ((x) << 4) #define AT91_SHDW_RTTWKEN (1 << 16) /* Real Time Timer Wake-up Enable */ +#define AT91_SHDW_RTCWKEN (1 << 17) /* Real Time Clock Wake-up Enable */ #define AT91_SHDW_SR 0x08 /* Shut Down Status Register */ #define AT91_SHDW_WAKEUP0 (1 << 0) /* Wake-up 0 Status */ diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 46d0a56ba825..1083739e3065 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -351,10 +351,87 @@ static void at91_dt_ramc(void) of_node_put(np); } +static struct of_device_id shdwc_ids[] = { + { .compatible = "atmel,at91sam9260-shdwc", }, + { .compatible = "atmel,at91sam9rl-shdwc", }, + { .compatible = "atmel,at91sam9x5-shdwc", }, + { /*sentinel*/ } +}; + +static const char *shdwc_wakeup_modes[] = { + [AT91_SHDW_WKMODE0_NONE] = "none", + [AT91_SHDW_WKMODE0_HIGH] = "high", + [AT91_SHDW_WKMODE0_LOW] = "low", + [AT91_SHDW_WKMODE0_ANYLEVEL] = "any", +}; + +const int at91_dtget_shdwc_wakeup_mode(struct device_node *np) +{ + const char *pm; + int err, i; + + err = of_property_read_string(np, "atmel,wakeup-mode", &pm); + if (err < 0) + return AT91_SHDW_WKMODE0_ANYLEVEL; + + for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++) + if (!strcasecmp(pm, shdwc_wakeup_modes[i])) + return i; + + return -ENODEV; +} + +static void at91_dt_shdwc(void) +{ + struct device_node *np; + int wakeup_mode; + u32 reg; + u32 mode = 0; + + np = of_find_matching_node(NULL, shdwc_ids); + if (!np) { + pr_debug("AT91: unable to find compatible shutdown (shdwc) conroller node in dtb\n"); + return; + } + + at91_shdwc_base = of_iomap(np, 0); + if (!at91_shdwc_base) + panic("AT91: unable to map shdwc cpu registers\n"); + + wakeup_mode = at91_dtget_shdwc_wakeup_mode(np); + if (wakeup_mode < 0) { + pr_warn("AT91: shdwc unknown wakeup mode\n"); + goto end; + } + + if (!of_property_read_u32(np, "atmel,wakeup-counter", ®)) { + if (reg > AT91_SHDW_CPTWK0_MAX) { + pr_warn("AT91: shdwc wakeup conter 0x%x > 0x%x reduce it to 0x%x\n", + reg, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX); + reg = AT91_SHDW_CPTWK0_MAX; + } + mode |= AT91_SHDW_CPTWK0_(reg); + } + + if (of_property_read_bool(np, "atmel,wakeup-rtc-timer")) + mode |= AT91_SHDW_RTCWKEN; + + if (of_property_read_bool(np, "atmel,wakeup-rtt-timer")) + mode |= AT91_SHDW_RTTWKEN; + + at91_shdwc_write(AT91_SHDW_MR, wakeup_mode | mode); + +end: + pm_power_off = at91sam9_poweroff; + + of_node_put(np); +} + void __init at91_dt_initialize(void) { at91_dt_rstc(); at91_dt_ramc(); + at91_dt_shdwc(); /* Init clock subsystem */ at91_dt_clock_init(); -- cgit v1.2.3 From 2419730f8f8ce04cce9e39a715c149283210ce27 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 21 Nov 2011 06:55:18 +0800 Subject: ARM: at91: usb ohci add dt support Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Acked-by: Grant Likely Acked-by: Greg Kroah-Hartman --- .../devicetree/bindings/usb/atmel-usb.txt | 19 ++++ drivers/usb/host/ohci-at91.c | 101 ++++++++++++++++++++- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/usb/atmel-usb.txt diff --git a/Documentation/devicetree/bindings/usb/atmel-usb.txt b/Documentation/devicetree/bindings/usb/atmel-usb.txt new file mode 100644 index 000000000000..6c7f728a362e --- /dev/null +++ b/Documentation/devicetree/bindings/usb/atmel-usb.txt @@ -0,0 +1,19 @@ +Atmel SOC USB controllers + +OHCI + +Required properties: + - compatible: Should be "atmel,at91rm9200-ohci" for USB controllers + used in host mode. + - num-ports: Number of ports. + - atmel,vbus-gpio: If present, specifies a gpio that needs to be + activated for the bus to be powered. + - atmel,oc-gpio: If present, specifies a gpio that needs to be + activated for the overcurrent detection. + +usb0: ohci@00500000 { + compatible = "atmel,at91rm9200-ohci", "usb-ohci"; + reg = <0x00500000 0x100000>; + interrupts = <20 4>; + num-ports = <2>; +}; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 8e855eb0bf89..db8963f5fbce 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -14,6 +14,8 @@ #include #include +#include +#include #include #include @@ -477,13 +479,109 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) return IRQ_HANDLED; } +#ifdef CONFIG_OF +static const struct of_device_id at91_ohci_dt_ids[] = { + { .compatible = "atmel,at91rm9200-ohci" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids); + +static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32); + +static int __devinit ohci_at91_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + int i, ret, gpio; + enum of_gpio_flags flags; + struct at91_usbh_data *pdata; + u32 ports; + + if (!np) + return 0; + + /* Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &at91_ohci_dma_mask; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + if (!of_property_read_u32(np, "num-ports", &ports)) + pdata->ports = ports; + + for (i = 0; i < 2; i++) { + gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags); + pdata->vbus_pin[i] = gpio; + if (!gpio_is_valid(gpio)) + continue; + pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW; + ret = gpio_request(gpio, "ohci_vbus"); + if (ret) { + dev_warn(&pdev->dev, "can't request vbus gpio %d", gpio); + continue; + } + ret = gpio_direction_output(gpio, !(flags & OF_GPIO_ACTIVE_LOW) ^ 1); + if (ret) + dev_warn(&pdev->dev, "can't put vbus gpio %d as output %d", + !(flags & OF_GPIO_ACTIVE_LOW) ^ 1, gpio); + } + + for (i = 0; i < 2; i++) { + gpio = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); + pdata->overcurrent_pin[i] = gpio; + if (!gpio_is_valid(gpio)) + continue; + ret = gpio_request(gpio, "ohci_overcurrent"); + if (ret) { + dev_err(&pdev->dev, "can't request overcurrent gpio %d", gpio); + continue; + } + + ret = gpio_direction_input(gpio); + if (ret) { + dev_err(&pdev->dev, "can't configure overcurrent gpio %d as input", gpio); + continue; + } + + ret = request_irq(gpio_to_irq(gpio), + ohci_hcd_at91_overcurrent_irq, + IRQF_SHARED, "ohci_overcurrent", pdev); + if (ret) { + gpio_free(gpio); + dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n"); + } + } + + pdev->dev.platform_data = pdata; + + return 0; +} +#else +static int __devinit ohci_at91_of_init(struct platform_device *pdev) +{ + return 0; +} +#endif + /*-------------------------------------------------------------------------*/ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) { - struct at91_usbh_data *pdata = pdev->dev.platform_data; + struct at91_usbh_data *pdata; int i; + i = ohci_at91_of_init(pdev); + + if (i) + return i; + + pdata = pdev->dev.platform_data; + if (pdata) { for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { if (!gpio_is_valid(pdata->vbus_pin[i])) @@ -596,5 +694,6 @@ static struct platform_driver ohci_hcd_at91_driver = { .driver = { .name = "at91_ohci", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(at91_ohci_dt_ids), }, }; -- cgit v1.2.3 From 6a0624599085e9e0c7b984c28443531849ab0459 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 21 Nov 2011 06:55:18 +0800 Subject: ARM: at91: dt: enable usb ohci for sam9g20, sam9g45 amd sam9x5 Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Cc: devicetree-discuss@lists.ozlabs.org --- arch/arm/boot/dts/at91sam9g20.dtsi | 7 +++++++ arch/arm/boot/dts/at91sam9g25ek.dts | 8 ++++++++ arch/arm/boot/dts/at91sam9g45.dtsi | 7 +++++++ arch/arm/boot/dts/at91sam9m10g45ek.dts | 6 ++++++ arch/arm/boot/dts/at91sam9x5.dtsi | 7 +++++++ arch/arm/boot/dts/usb_a9g20.dts | 5 +++++ arch/arm/mach-at91/at91sam9260.c | 1 + arch/arm/mach-at91/at91sam9g45.c | 1 + arch/arm/mach-at91/at91sam9x5.c | 4 +++- 9 files changed, 45 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index 9a0647bb387f..f091d679bd4c 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -208,6 +208,13 @@ >; status = "disabled"; }; + + usb0: ohci@00500000 { + compatible = "atmel,at91rm9200-ohci", "usb-ohci"; + reg = <0x00500000 0x100000>; + interrupts = <20 4>; + status = "disabled"; + }; }; i2c@0 { diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts index c7596bf26388..93d5e361533f 100644 --- a/arch/arm/boot/dts/at91sam9g25ek.dts +++ b/arch/arm/boot/dts/at91sam9g25ek.dts @@ -33,5 +33,13 @@ status = "okay"; }; }; + + usb0: ohci@00600000 { + status = "okay"; + num-ports = <2>; + atmel,vbus-gpio = <&pioD 19 0 + &pioD 20 0 + >; + }; }; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 8908f078c307..4ab8a2502697 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -217,6 +217,13 @@ >; status = "disabled"; }; + + usb0: ohci@00700000 { + compatible = "atmel,at91rm9200-ohci", "usb-ohci"; + reg = <0x00700000 0x100000>; + interrupts = <22 4>; + status = "disabled"; + }; }; i2c@0 { diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index a8958241f1d7..0c101ada9d8f 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -68,7 +68,13 @@ label = "data"; reg = <0x4000000 0xC000000>; }; + }; + usb0: ohci@00700000 { + status = "okay"; + num-ports = <2>; + atmel,vbus-gpio = <&pioD 1 0 + &pioD 3 0>; }; }; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 20155ccbbe14..1d8b6ac945f8 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -207,6 +207,13 @@ >; status = "disabled"; }; + + usb0: ohci@00600000 { + compatible = "atmel,at91rm9200-ohci", "usb-ohci"; + reg = <0x00600000 0x100000>; + interrupts = <22 4>; + status = "disabled"; + }; }; i2c@0 { diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts index 73f1dc48f307..748d4c2f889f 100644 --- a/arch/arm/boot/dts/usb_a9g20.dts +++ b/arch/arm/boot/dts/usb_a9g20.dts @@ -84,6 +84,11 @@ reg = <0x7ca0000 0x8360000>; }; }; + + usb0: ohci@00500000 { + num-ports = <2>; + status = "okay"; + }; }; leds { diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 14b5a9c9a514..d1e5750a6a04 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -216,6 +216,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t0_clk", "fffdc000.timer", &tc3_clk), CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk), CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk), + CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 0014573dfe17..f58775e76325 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -232,6 +232,7 @@ static struct clk_lookup periph_clocks_lookups[] = { /* more tc lookup table for DT entries */ CLKDEV_CON_DEV_ID("t0_clk", "fff7c000.timer", &tcb0_clk), CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk), + CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index 01b2bd816a9a..ec65ef7abfc9 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -131,7 +131,7 @@ static struct clk dma1_clk = { .type = CLK_TYPE_PERIPHERAL, }; static struct clk uhphs_clk = { - .name = "uhphs_clk", + .name = "uhphs", .pmc_mask = 1 << AT91SAM9X5_ID_UHPHS, .type = CLK_TYPE_PERIPHERAL, }; @@ -230,6 +230,8 @@ static struct clk_lookup periph_clocks_lookups[] = { /* additional fake clock for macb_hclk */ CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb0_clk), CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk), + CLKDEV_CON_DEV_ID("hclk", "600000.ohci", &uhphs_clk), + CLKDEV_CON_DEV_ID("ohci_clk", "600000.ohci", &uhphs_clk), }; /* -- cgit v1.2.3 From 9d843003357f0e4948ac624a99a411a2dc37dfaf Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 22 Nov 2011 12:11:13 +0800 Subject: ARM: at91: usb ehci add dt support Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Acked-by: Grant Likely Acked-by: Greg Kroah-Hartman --- .../devicetree/bindings/usb/atmel-usb.txt | 12 +++++++++++ drivers/usb/host/ehci-atmel.c | 24 +++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/atmel-usb.txt b/Documentation/devicetree/bindings/usb/atmel-usb.txt index 6c7f728a362e..0143d7c5b4b9 100644 --- a/Documentation/devicetree/bindings/usb/atmel-usb.txt +++ b/Documentation/devicetree/bindings/usb/atmel-usb.txt @@ -17,3 +17,15 @@ usb0: ohci@00500000 { interrupts = <20 4>; num-ports = <2>; }; + +EHCI + +Required properties: + - compatible: Should be "atmel,at91sam9g45-ehci" for USB controllers + used in host mode. + +usb1: ehci@00800000 { + compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; + reg = <0x00800000 0x100000>; + interrupts = <22 4>; +}; diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index a5a3ef1f0096..19f318ababa2 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -13,6 +13,7 @@ #include #include +#include /* interface and function clocks */ static struct clk *iclk, *fclk; @@ -115,6 +116,8 @@ static const struct hc_driver ehci_atmel_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32); + static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; @@ -137,6 +140,13 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) goto fail_create_hcd; } + /* Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &at91_ehci_dma_mask; + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; @@ -225,9 +235,21 @@ static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id atmel_ehci_dt_ids[] = { + { .compatible = "atmel,at91sam9g45-ehci" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids); +#endif + static struct platform_driver ehci_atmel_driver = { .probe = ehci_atmel_drv_probe, .remove = __devexit_p(ehci_atmel_drv_remove), .shutdown = usb_hcd_platform_shutdown, - .driver.name = "atmel-ehci", + .driver = { + .name = "atmel-ehci", + .of_match_table = of_match_ptr(atmel_ehci_dt_ids), + }, }; -- cgit v1.2.3 From 62c5553ab7ecf23e7b5464a59d728ab94479adbb Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 22 Nov 2011 12:11:13 +0800 Subject: ARM: at91: dt: enable usb ehci for sam9g45 and sam9x5 make the ECHI depends on ARCH_AT91 Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Cc: devicetree-discuss@lists.ozlabs.org --- arch/arm/boot/dts/at91sam9g25ek.dts | 4 ++++ arch/arm/boot/dts/at91sam9g45.dtsi | 7 +++++++ arch/arm/boot/dts/at91sam9m10g45ek.dts | 4 ++++ arch/arm/boot/dts/at91sam9x5.dtsi | 7 +++++++ arch/arm/mach-at91/at91sam9g45.c | 1 + arch/arm/mach-at91/at91sam9x5.c | 1 + drivers/usb/Kconfig | 2 +- 7 files changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts index 93d5e361533f..ac0dc0031dda 100644 --- a/arch/arm/boot/dts/at91sam9g25ek.dts +++ b/arch/arm/boot/dts/at91sam9g25ek.dts @@ -41,5 +41,9 @@ &pioD 20 0 >; }; + + usb1: ehci@00700000 { + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 4ab8a2502697..3d0c32fb218f 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -224,6 +224,13 @@ interrupts = <22 4>; status = "disabled"; }; + + usb1: ehci@00800000 { + compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; + reg = <0x00800000 0x100000>; + interrupts = <22 4>; + status = "disabled"; + }; }; i2c@0 { diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index 0c101ada9d8f..c4c8ae4123d5 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -76,6 +76,10 @@ atmel,vbus-gpio = <&pioD 1 0 &pioD 3 0>; }; + + usb1: ehci@00800000 { + status = "okay"; + }; }; leds { diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 1d8b6ac945f8..c111001f254e 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -214,6 +214,13 @@ interrupts = <22 4>; status = "disabled"; }; + + usb1: ehci@00700000 { + compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; + reg = <0x00700000 0x100000>; + interrupts = <22 4>; + status = "disabled"; + }; }; i2c@0 { diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index f58775e76325..df3bceacc86c 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -233,6 +233,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t0_clk", "fff7c000.timer", &tcb0_clk), CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk), CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk), + CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index ec65ef7abfc9..b6831eeb7b76 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c @@ -232,6 +232,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk), CLKDEV_CON_DEV_ID("hclk", "600000.ohci", &uhphs_clk), CLKDEV_CON_DEV_ID("ohci_clk", "600000.ohci", &uhphs_clk), + CLKDEV_CON_DEV_ID("ehci_clk", "700000.ehci", &uhphs_clk), }; /* diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 75823a1abeb6..7fe4902d9e51 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -65,7 +65,7 @@ config USB_ARCH_HAS_EHCI default y if PPC_MPC512x default y if ARCH_IXP4XX default y if ARCH_W90X900 - default y if ARCH_AT91SAM9G45 + default y if ARCH_AT91 default y if ARCH_MXC default y if ARCH_OMAP3 default y if ARCH_CNS3XXX -- cgit v1.2.3