diff options
author | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-05 10:12:53 +0000 |
---|---|---|
committer | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-05 10:12:53 +0000 |
commit | 5c105d9f3fd086aff195d3849dcf847d6b0bd927 (patch) | |
tree | 1229a11f725bfa58aa7c57a76898553bb5f6654a /target/linux/at91/files | |
download | openwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.tar.gz openwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.zip |
branch Attitude Adjustment
git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@33625 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/at91/files')
-rw-r--r-- | target/linux/at91/files/arch/arm/mach-at91/board-tqma9263.c | 219 | ||||
-rw-r--r-- | target/linux/at91/files/drivers/misc/at91-adc.c | 355 | ||||
-rw-r--r-- | target/linux/at91/files/drivers/misc/at91_adc.h | 62 | ||||
-rw-r--r-- | target/linux/at91/files/drivers/mtd/at91part.c | 120 |
4 files changed, 756 insertions, 0 deletions
diff --git a/target/linux/at91/files/arch/arm/mach-at91/board-tqma9263.c b/target/linux/at91/files/arch/arm/mach-at91/board-tqma9263.c new file mode 100644 index 000000000..cae1fe935 --- /dev/null +++ b/target/linux/at91/files/arch/arm/mach-at91/board-tqma9263.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2008 I2SE GmbH + * Copyright (C) 2010 IEQualize GmbH + * Copyright (C) 2010-2011 Michael Heimpold + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/fb.h> + +#include <mach/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at91sam9_smc.h> + +#include <video/atmel_lcdc.h> + +#include "sam9_smc.h" +#include "generic.h" + +#include <linux/atmel_serial.h> + + +static void __init tqma9263_map_io(void) +{ + unsigned pins; + + /* Initialize processor: 18.432 MHz crystal */ + at91_initialize(18432000); + + /* DGBU on ttyS0. (Rx & Tx only) */ + at91_register_uart(0, 0, 0); + + /* USART0 on ttyS1 */ + pins = ATMEL_UART_CTS | ATMEL_UART_RTS | + ATMEL_UART_DSR | ATMEL_UART_DTR | + ATMEL_UART_DCD | ATMEL_UART_RI; + at91_register_uart(AT91SAM9263_ID_US0, 1, pins); + + /* USART1 on ttyS2 */ + pins = ATMEL_UART_RTS; + at91_register_uart(AT91SAM9263_ID_US1, 2, pins); + + /* USART2 on ttyS3 */ + pins = ATMEL_UART_RTS; + at91_register_uart(AT91SAM9263_ID_US2, 3, pins); + + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + + +/* + * USB Host port + */ +static struct at91_usbh_data __initdata tqma9263_usbh_data = { + .ports = 2, + .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 }, + .vbus_pin_active_low = 0, +}; + + +/* + * USB Device port + */ +static struct at91_udc_data __initdata tqma9263_udc_data = { + .vbus_pin = AT91_PIN_PA25, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata tqma9263_mmc_data = { + .wire4 = 1, + .det_pin = AT91_PIN_PE18, + .wp_pin = AT91_PIN_PB28, +}; + + +/* + * MACB Ethernet device + */ +static struct macb_platform_data __initdata tqma9263_macb_data = { + .phy_irq_pin = AT91_PIN_PE31, + .is_rmii = 1, +}; + + +/* + * I2C devices + */ +static struct i2c_board_info __initdata tqma9263_i2c_devices[] = { + { + I2C_BOARD_INFO("pcf8563", 0x51), + }, + { + I2C_BOARD_INFO("24c04", 0x52), + }, +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata tqma9263_nand_partition[] = { + { + .name = "uboot", + .offset = 0, + .size = 3 * SZ_128K, + }, + { + .name = "uboot-env", + .offset = MTDPART_OFS_NXTBLK, + .size = SZ_128K, + }, + { + .name = "linux", + .offset = MTDPART_OFS_NXTBLK, + .size = SZ_2M, + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition * __init nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(tqma9263_nand_partition); + return tqma9263_nand_partition; +} + +static struct atmel_nand_data __initdata tqma9263_nand_data = { + .ale = 21, + .cle = 22, + .rdy_pin = AT91_PIN_PD14, + .enable_pin = AT91_PIN_PD15, +}; + +static struct sam9_smc_config __initdata tqma9263_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static void __init tqma9263_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(0, 3, &tqma9263_nand_smc_config); + + at91_add_device_nand(&tqma9263_nand_data); +} + + +static void __init tqma9263_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&tqma9263_usbh_data); + /* USB Device */ + at91_add_device_udc(&tqma9263_udc_data); + /* MMC */ + at91_add_device_mmc(1, &tqma9263_mmc_data); + /* I2C */ + at91_add_device_i2c(tqma9263_i2c_devices, ARRAY_SIZE(tqma9263_i2c_devices)); + /* Ethernet */ + at91_add_device_eth(&tqma9263_macb_data); + /* NAND flash */ + tqma9263_add_device_nand(); +} + +MACHINE_START(TQMA9263, "TQ Components TQMa9263") + /* Maintainer: Michael Heimpold */ + .timer = &at91sam926x_timer, + .map_io = tqma9263_map_io, + .init_irq = at91_init_irq_default, + .init_machine = tqma9263_board_init, +MACHINE_END diff --git a/target/linux/at91/files/drivers/misc/at91-adc.c b/target/linux/at91/files/drivers/misc/at91-adc.c new file mode 100644 index 000000000..90ea8181b --- /dev/null +++ b/target/linux/at91/files/drivers/misc/at91-adc.c @@ -0,0 +1,355 @@ +/* + * Driver for ADC on Atmel AT91 SoC Family + * + * Copyright (C) 2010 Claudio Mignanti - c.mignanti@gmail.com + * Based on http://www.at91.com/forum/viewtopic.php/p,9409/#p9409 + * + * Copyright (C) 2010 Stefano Barbato - stefano@codesink.org + * + * 2010/05/18 Antonio Galea + * Sysfs device model, different drivers integration + * + * WISHLIST: + * - concurrent access control + * - add support for dynamic reconfiguration + * - hardware triggers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * --------------------------------------------------------------------------- +*/ + +#include <linux/cdev.h> +#include <linux/clk.h> +#include <linux/fs.h> +#include <linux/gpio.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/smp_lock.h> + +#include <asm/io.h> + +#include "at91_adc.h" + +#define DRV_CLASS "at91_adc" + +#define ADC_REQUEST 1 //un-used atm +#define ADC_READ 2 +#define ADC_FREE 3 + +/* Device functions */ +#define at91_adc_read(reg) ioread32(at91_adc_base + (reg)) +#define at91_adc_write(reg, val) iowrite32((val), at91_adc_base + (reg)) +#define AT91_DEFAULT_CONFIG AT91_ADC_SHTIM | \ + AT91_ADC_STARTUP | \ + AT91_ADC_PRESCAL | \ + AT91_ADC_SLEEP + +static void at91_adc_device_release(struct device *dev) {} + +struct platform_device at91_adc_device = { + .name = "at91_adc", + .id = -1, + .dev.release = at91_adc_device_release, +}; + +struct clk *at91_adc_clk; +void __iomem *at91_adc_base; +void __iomem *at91_pioc_base; +static struct cdev *at91_adc_cdev = NULL; +static dev_t at91_adc_devno = 0; +static struct class *at91_adc_class = NULL; + +static int at91_adc_read_chan(int chan){ + int val, sr; + + if(chan<0 || chan>3){ + return -EINVAL; + } + /* disable pull-up resistor */ + iowrite32(1 << chan, at91_pioc_base + 0x60); + + at91_adc_write(AT91_ADC_CHER,AT91_ADC_CH(chan)); // Enable Channel + at91_adc_write(AT91_ADC_CR,AT91_ADC_START); //Start the ADC + + for(sr=0; !(sr & AT91_ADC_EOC(chan)); sr=at91_adc_read(AT91_ADC_SR)) + cpu_relax(); + + val=at91_adc_read(AT91_ADC_CHR(chan)) & AT91_ADC_DATA; //Read up to 10 bits + + return val; +} + +/* PC0 -> AD0 + PC1 -> AD1 + PC2 -> AD2 + PC3 -> AD3 */ +static int mux_chan (int chan, int operation) { + + int pin_chan; + + if(chan<0 || chan>3){ + return -EINVAL; + } + + switch (chan) { + case 0: + pin_chan=AT91_PIN_PC0; + break; + case 1: + pin_chan=AT91_PIN_PC1; + break; + case 2: + pin_chan=AT91_PIN_PC2; + break; + case 3: + pin_chan=AT91_PIN_PC3; + break; + default: + return -EINVAL; + } + + if (operation == 1) //request_chan + at91_set_A_periph(pin_chan, 0); //Mux PIN to GPIO + else //free_chan + at91_set_B_periph(pin_chan, 0); //Mux PIN to GPIO + + return 0; +} + +static int at91_adc_config(int requested_config){ + int actual_config; + + at91_adc_write(AT91_ADC_CR,AT91_ADC_SWRST); //Reset the ADC + at91_adc_write(AT91_ADC_MR,requested_config); //Mode setup + actual_config = at91_adc_read(AT91_ADC_MR); //Read it back + + return (requested_config==actual_config? 0: -EINVAL); +} + +/* Sysfs interface */ +static ssize_t at91_adc_chanX_show( + struct device *dev, struct device_attribute *attr, char *buf ){ + + ssize_t status = 0; + int chan = -1; + int value; + + if(strlen(attr->attr.name)==5 && strncmp(attr->attr.name,"chan",4)==0){ + chan = attr->attr.name[4]-'0'; + } + + if(chan<0 || chan>3){ + return -EIO; + } + + value = at91_adc_read_chan(chan); + status = sprintf(buf, "%d\n", value); + + return status; +} + +static DEVICE_ATTR(chan0, 0444, at91_adc_chanX_show, NULL); +static DEVICE_ATTR(chan1, 0444, at91_adc_chanX_show, NULL); +static DEVICE_ATTR(chan2, 0444, at91_adc_chanX_show, NULL); +static DEVICE_ATTR(chan3, 0444, at91_adc_chanX_show, NULL); + +static const struct attribute *at91_adc_dev_attrs[] = { + &dev_attr_chan0.attr, + &dev_attr_chan1.attr, + &dev_attr_chan2.attr, + &dev_attr_chan3.attr, + NULL, +}; + +static const struct attribute_group at91_adc_dev_attr_group = { + .attrs = (struct attribute **) at91_adc_dev_attrs, +}; + +/* IOCTL interface */ +#ifdef HAVE_UNLOCKED_IOCTL +static long at91_adc_unlocked_ioctl( + struct file *file, unsigned int cmd, unsigned long arg){ +#else +static int at91_adc_ioctl( + struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ +#endif + + long retval = 0; + +#ifdef HAVE_UNLOCKED_IOCTL + lock_kernel(); +#endif + + switch (cmd) { + case ADC_REQUEST: + retval = mux_chan ((int)arg, 1); + break; + + case ADC_READ: + retval = at91_adc_read_chan((int)arg); + break; + + case ADC_FREE: + retval = mux_chan ((int)arg, 0); + break; + + default: + retval = -EINVAL; + } + +#ifdef HAVE_UNLOCKED_IOCTL + unlock_kernel(); +#endif + + return retval; +} + +struct file_operations at91_adc_fops = { + .owner = THIS_MODULE, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = at91_adc_unlocked_ioctl, +#else + .ioctl = at91_adc_ioctl, +#endif +}; + +static void at91_adc_cdev_teardown(void){ + if(at91_adc_class){ + device_destroy(at91_adc_class, at91_adc_devno); + class_destroy(at91_adc_class); + } + + if(at91_adc_devno){ + unregister_chrdev_region(at91_adc_devno,1); + if(at91_adc_cdev){ cdev_del(at91_adc_cdev); } + } + + at91_adc_devno = 0; + at91_adc_cdev = NULL; + at91_adc_class = NULL; + return; +} + +static int at91_adc_cdev_setup(void){ + + int status; + /* alloc a new device number (major: dynamic, minor: 0) */ + status = alloc_chrdev_region(&at91_adc_devno,0,1,at91_adc_device.name); + + if(status){ + goto err; + } + + /* create a new char device */ + at91_adc_cdev = cdev_alloc(); + if(at91_adc_cdev == NULL){ status=-ENOMEM; goto err; } + at91_adc_cdev->owner = THIS_MODULE; + at91_adc_cdev->ops = &at91_adc_fops; + status = cdev_add(at91_adc_cdev,at91_adc_devno,1); + if(status){ + goto err; + } + + /* register the class */ + at91_adc_class = class_create(THIS_MODULE, DRV_CLASS); + if(IS_ERR(at91_adc_class)){ status=-EFAULT; goto err; } + device_create(at91_adc_class, NULL, at91_adc_devno, NULL, at91_adc_device.name); + printk(KERN_INFO "Major: %u; minor: %u\n", \ + MAJOR(at91_adc_devno), MINOR(at91_adc_devno) \ + ); + + return 0; + +err: + at91_adc_cdev_teardown(); + return status; +} + +/* Module init/exit */ +static int __init at91_adc_init(void){ + + int status; + + at91_adc_clk = clk_get(NULL,"adc_clk"); + clk_enable(at91_adc_clk); + + at91_adc_base = ioremap(AT91SAM9260_BASE_ADC,SZ_256); + if(!at91_adc_base){ + status=-ENODEV; + goto fail_no_iomem_adc; + } + + at91_pioc_base = ioremap(AT91_BASE_SYS + AT91_PIOC,SZ_512); + if(!at91_pioc_base){ + status=-ENODEV; + goto fail_no_iomem_pioc; + } + + status = platform_device_register(&at91_adc_device); + if(status){ + goto fail_no_dev; + } + + status = at91_adc_config(AT91_DEFAULT_CONFIG); + if(status){ + goto fail_no_config; + } + + status = sysfs_create_group( + &(at91_adc_device.dev.kobj), &at91_adc_dev_attr_group + ); + + if(status){ + goto fail_no_sysfs; + } + + status = at91_adc_cdev_setup(); + if(status){ + goto fail_no_cdev; + } + + printk(KERN_INFO "Registered device at91_adc.\n"); + return 0; + +fail_no_cdev: +fail_no_sysfs: + // nothing to undo +fail_no_config: + platform_device_unregister(&at91_adc_device); +fail_no_dev: + iounmap(at91_adc_base); +fail_no_iomem_pioc: + iounmap(at91_pioc_base); +fail_no_iomem_adc: + clk_disable(at91_adc_clk); + clk_put(at91_adc_clk); + return status; +} + +static void __exit at91_adc_exit(void){ + + at91_adc_cdev_teardown(); + platform_device_unregister(&at91_adc_device); + iounmap(at91_adc_base); + iounmap(at91_pioc_base); + + clk_disable(at91_adc_clk); + clk_put(at91_adc_clk); + + printk(KERN_INFO "Unregistered device at91_adc.\n"); +} + +module_init(at91_adc_init); +module_exit(at91_adc_exit); + +MODULE_AUTHOR("Paul Kavan"); +MODULE_AUTHOR("Claudio Mignanti"); +MODULE_AUTHOR("Antonio Galea"); +MODULE_AUTHOR("Stefano Barbato"); +MODULE_DESCRIPTION("ADC Driver for the AT91SAM9G20"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/at91/files/drivers/misc/at91_adc.h b/target/linux/at91/files/drivers/misc/at91_adc.h new file mode 100644 index 000000000..2d6f01d84 --- /dev/null +++ b/target/linux/at91/files/drivers/misc/at91_adc.h @@ -0,0 +1,62 @@ +/* + * include/asm-arm/arch-at91/at91_adc.h + * + * Copyright (C) SAN People + * + * Analog-to-Digital Converter (ADC) registers. + * Based on AT91SAM9260 datasheet revision D. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91_ADC_H +#define AT91_ADC_H + +#define AT91_ADC_CR 0x00 /* Control Register */ +#define AT91_ADC_SWRST (1 << 0) /* Software Reset */ +#define AT91_ADC_START (1 << 1) /* Start Conversion */ + +#define AT91_ADC_MR 0x04 /* Mode Register */ +#define AT91_ADC_TRGEN (1 << 0) /* Trigger Enable */ +#define AT91_ADC_TRGSEL (7 << 1) /* Trigger Selection */ +#define AT91_ADC_TRGSEL_TC0 (0 << 1) +#define AT91_ADC_TRGSEL_TC1 (1 << 1) +#define AT91_ADC_TRGSEL_TC2 (2 << 1) +#define AT91_ADC_TRGSEL_EXTERNAL (6 << 1) +#define AT91_ADC_LOWRES (1 << 4) /* Low Resolution */ +#define AT91_ADC_SLEEP (1 << 5) /* Sleep Mode */ +#define AT91_ADC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ +#define AT91_ADC_PRESCAL_(x) ((x) << 8) +#define AT91_ADC_STARTUP (0x1f << 16) /* Startup Up Time */ +#define AT91_ADC_STARTUP_(x) ((x) << 16) +#define AT91_ADC_SHTIM (0xf << 24) /* Sample & Hold Time */ +#define AT91_ADC_SHTIM_(x) ((x) << 24) + +#define AT91_ADC_CHER 0x10 /* Channel Enable Register */ +#define AT91_ADC_CHDR 0x14 /* Channel Disable Register */ +#define AT91_ADC_CHSR 0x18 /* Channel Status Register */ +#define AT91_ADC_CH(n) (1 << (n)) /* Channel Number */ + +#define AT91_ADC_SR 0x1C /* Status Register */ +#define AT91_ADC_EOC(n) (1 << (n)) /* End of Conversion on Channel N */ +#define AT91_ADC_OVRE(n) (1 << ((n) + 8))/* Overrun Error on Channel N */ +#define AT91_ADC_DRDY (1 << 16) /* Data Ready */ +#define AT91_ADC_GOVRE (1 << 17) /* General Overrun Error */ +#define AT91_ADC_ENDRX (1 << 18) /* End of RX Buffer */ +#define AT91_ADC_RXFUFF (1 << 19) /* RX Buffer Full */ + +#define AT91_ADC_LCDR 0x20 /* Last Converted Data Register */ +#define AT91_ADC_LDATA (0x3ff) + +#define AT91_ADC_IER 0x24 /* Interrupt Enable Register */ +#define AT91_ADC_IDR 0x28 /* Interrupt Disable Register */ +#define AT91_ADC_IMR 0x2C /* Interrupt Mask Register */ + +#define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */ +#define AT91_ADC_DATA (0x3ff) + +#endif + diff --git a/target/linux/at91/files/drivers/mtd/at91part.c b/target/linux/at91/files/drivers/mtd/at91part.c new file mode 100644 index 000000000..d9c55ed32 --- /dev/null +++ b/target/linux/at91/files/drivers/mtd/at91part.c @@ -0,0 +1,120 @@ +/* + * + * Copyright (C) 2007 OpenWrt.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Atmel AT91 flash partition table. (Modified by Hamish Guthrie). + * Based on ar7 map by Felix Fietkau. + * + */ + +#include <linux/kernel.h> +#include <linux/slab.h> + +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/bootmem.h> +#include <linux/squashfs_fs.h> + +static struct mtd_partition at91_parts[6]; + +static int create_mtd_partitions(struct mtd_info *master, + struct mtd_partition **pparts, + unsigned long origin) +{ + unsigned int offset, len; + unsigned int pre_size = 0x42000, root_max = 0x362400; + unsigned char buf[512]; + struct squashfs_super_block *sb = (struct squashfs_super_block *) buf; + + printk("Parsing AT91 partition map...\n"); + + at91_parts[0].name = "loaders"; + at91_parts[0].offset = 0; + at91_parts[0].size = 0x21000; + at91_parts[0].mask_flags = MTD_WRITEABLE; + + at91_parts[1].name = "ubparams"; + at91_parts[1].offset = 0x21000; + at91_parts[1].size = 0x8400; + at91_parts[1].mask_flags = 0; + + at91_parts[2].name = "kernel"; + at91_parts[2].offset = pre_size; + at91_parts[2].size = 0; + at91_parts[2].mask_flags = 0; + + at91_parts[3].name = "rootfs"; + at91_parts[3].offset = 0; + at91_parts[3].size = 0; + at91_parts[3].mask_flags = 0; + + for(offset = pre_size; offset < root_max; offset += master->erasesize) { + + memset(&buf, 0xe5, sizeof(buf)); + + if (master->read(master, offset, sizeof(buf), &len, buf) || len != sizeof(buf)) + break; + + if (*((__u32 *) buf) == SQUASHFS_MAGIC) { + printk(KERN_INFO "%s: Filesystem type: squashfs, size=0x%x\n", + master->name, (u32) sb->bytes_used); + + at91_parts[3].size = sb->bytes_used; + at91_parts[3].offset = offset; + len = at91_parts[3].offset + at91_parts[3].size; + len = ((len / (master->erasesize * 8)) + 1) * master->erasesize * 8; + at91_parts[3].size = len - at91_parts[3].offset; + at91_parts[2].size = offset - at91_parts[2].offset; + break; + } + } + + if (at91_parts[3].size == 0) { + printk(KERN_NOTICE "%s: Couldn't find root filesystem\n", master->name); + return -1; + } + + at91_parts[4].name = "rootfs_data"; + at91_parts[4].offset = root_max; + at91_parts[4].size = master->size - root_max; + at91_parts[4].mask_flags = 0; + + at91_parts[5].name = "complete"; + at91_parts[5].offset = 0; + at91_parts[5].size = master->size; + at91_parts[5].mask_flags = 0; + + *pparts = at91_parts; + return 6; +} + +static struct mtd_part_parser at91_parser = { + .owner = THIS_MODULE, + .parse_fn = create_mtd_partitions, + .name = "at91part", +}; + +static int __init at91_parser_init(void) +{ + return register_mtd_parser(&at91_parser); +} + +module_init(at91_parser_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Felix Fietkau, Eugene Konev, Hamish Guthrie"); +MODULE_DESCRIPTION("MTD partitioning for Atmel at91"); |