diff options
Diffstat (limited to 'package/broadcom-mmc')
-rw-r--r-- | package/broadcom-mmc/Makefile | 46 | ||||
-rw-r--r-- | package/broadcom-mmc/src/Makefile | 7 | ||||
-rw-r--r-- | package/broadcom-mmc/src/mmc.c | 676 |
3 files changed, 0 insertions, 729 deletions
diff --git a/package/broadcom-mmc/Makefile b/package/broadcom-mmc/Makefile deleted file mode 100644 index 509e993c4..000000000 --- a/package/broadcom-mmc/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (C) 2007 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=broadcom-mmc -PKG_VERSION:=0.1 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/package.mk - -MAKEFLAGS_KMOD:= -C "$(LINUX_DIR)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - PATH="$(TARGET_PATH)" \ - SUBDIRS="$(PKG_BUILD_DIR)" - -define KernelPackage/broadcom-mmc - SUBMENU:=Other modules - DEPENDS:=@TARGET_brcm_2_4 - TITLE:=Kernel driver for the Linksys WRT54G MM/SD-Card Mod - URL:=http://kiel.kool.dk/ - FILES:=$(PKG_BUILD_DIR)/mmc.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,80,mmc) -endef - -define KernelPackage/broadcom-mmc/description - Kernel driver for the Linksys WRT54G MM/SD-Card Mod -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) $(MAKEFLAGS_KMOD) \ - modules -endef - -$(eval $(call KernelPackage,broadcom-mmc)) diff --git a/package/broadcom-mmc/src/Makefile b/package/broadcom-mmc/src/Makefile deleted file mode 100644 index ccf07b169..000000000 --- a/package/broadcom-mmc/src/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -obj-m := mmc.o - -ifeq ($(MAKING_MODULES),1) - --include $(TOPDIR)/Rules.make -endif - diff --git a/package/broadcom-mmc/src/mmc.c b/package/broadcom-mmc/src/mmc.c deleted file mode 100644 index 64cb8d97b..000000000 --- a/package/broadcom-mmc/src/mmc.c +++ /dev/null @@ -1,676 +0,0 @@ -#include <linux/delay.h> -#include <linux/timer.h> - -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/blkpg.h> -#include <linux/hdreg.h> -#include <linux/major.h> -#include <asm/uaccess.h> -#include <asm/io.h> - -#define DEVICE_NAME "mmc" -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) -#define MAJOR_NR 121 - -#include <linux/blk.h> - -MODULE_AUTHOR("Madsuk/Rohde"); -MODULE_DESCRIPTION("Driver MMC/SD-Cards"); -MODULE_SUPPORTED_DEVICE("WRT54G"); -MODULE_LICENSE("GPL"); - -#define SD_DI 0x20 -#define SD_DO 0x10 -#define SD_CLK 0x08 -#define SD_CS 0x80 - -/* we have only one device */ -static int hd_sizes[1<<6]; -static int hd_blocksizes[1<<6]; -static int hd_hardsectsizes[1<<6]; -static int hd_maxsect[1<<6]; -static struct hd_struct hd[1<<6]; - -static struct timer_list mmc_timer; -static int mmc_media_detect = 0; -static int mmc_media_changed = 1; - -typedef unsigned int uint32; - -static unsigned char port_state = 0x00; -static volatile uint32 *gpioaddr_input = (uint32 *)0xb8000060; -static volatile uint32 *gpioaddr_output = (uint32 *)0xb8000064; -static volatile uint32 *gpioaddr_enable = (uint32 *)0xb8000068; -static volatile uint32 *gpioaddr_control = (uint32 *)0xb800006c; - -static void mmc_spi_cs_low(void) -{ - port_state &= ~(SD_CS); - *gpioaddr_output = port_state; -} - -static void mmc_spi_cs_high(void) -{ - port_state |= SD_CS; - *gpioaddr_output = port_state; -} - -static unsigned char mmc_spi_io(unsigned char data_out) -{ - int i; - unsigned char result = 0, tmp_data = 0; - - for(i=0; i<8; i++) { - if(data_out & (0x01 << (7-i))) - port_state |= SD_DI; - else - port_state &= ~SD_DI; - - *gpioaddr_output = port_state; - port_state |= SD_CLK; - *gpioaddr_output = port_state; - - tmp_data = *gpioaddr_input; - - port_state &= ~SD_CLK; - *gpioaddr_output = port_state; - - result <<= 1; - - if(tmp_data & SD_DO) - result |= 1; - } - - return(result); -} - -static int mmc_write_block(unsigned int dest_addr, unsigned char *data) -{ - unsigned int address; - unsigned char r = 0; - unsigned char ab0, ab1, ab2, ab3; - int i; - - address = dest_addr; - - ab3 = 0xff & (address >> 24); - ab2 = 0xff & (address >> 16); - ab1 = 0xff & (address >> 8); - ab0 = 0xff & address; - mmc_spi_cs_low(); - for (i = 0; i < 4; i++) mmc_spi_io(0xff); - mmc_spi_io(0x58); - mmc_spi_io(ab3); /* msb */ - mmc_spi_io(ab2); - mmc_spi_io(ab1); - mmc_spi_io(ab0); /* lsb */ - mmc_spi_io(0xff); - for (i = 0; i < 8; i++) - { - r = mmc_spi_io(0xff); - if (r == 0x00) break; - } - if (r != 0x00) - { - mmc_spi_cs_high(); - mmc_spi_io(0xff); - return(1); - } - - mmc_spi_io(0xfe); - for (i = 0; i < 512; i++) mmc_spi_io(data[i]); - for (i = 0; i < 2; i++) mmc_spi_io(0xff); - - for (i = 0; i < 1000000; i++) - { - r = mmc_spi_io(0xff); - if (r == 0xff) break; - } - if (r != 0xff) - { - mmc_spi_cs_high(); - mmc_spi_io(0xff); - return(3); - } - mmc_spi_cs_high(); - mmc_spi_io(0xff); - return(0); -} - -static int mmc_read_block(unsigned char *data, unsigned int src_addr) -{ - unsigned int address; - unsigned char r = 0; - unsigned char ab0, ab1, ab2, ab3; - int i; - - address = src_addr; - - ab3 = 0xff & (address >> 24); - ab2 = 0xff & (address >> 16); - ab1 = 0xff & (address >> 8); - ab0 = 0xff & address; - - mmc_spi_cs_low(); - for (i = 0; i < 4; i++) mmc_spi_io(0xff); - mmc_spi_io(0x51); - mmc_spi_io(ab3); /* msb */ - mmc_spi_io(ab2); - mmc_spi_io(ab1); - mmc_spi_io(ab0); /* lsb */ - - mmc_spi_io(0xff); - for (i = 0; i < 8; i++) - { - r = mmc_spi_io(0xff); - if (r == 0x00) break; - } - if (r != 0x00) - { - mmc_spi_cs_high(); - mmc_spi_io(0xff); - return(1); - } - for (i = 0; i < 100000; i++) - { - r = mmc_spi_io(0xff); - if (r == 0xfe) break; - } - if (r != 0xfe) - { - mmc_spi_cs_high(); - mmc_spi_io(0xff); - return(2); - } - for (i = 0; i < 512; i++) - { - r = mmc_spi_io(0xff); - data[i] = r; - } - for (i = 0; i < 2; i++) - { - r = mmc_spi_io(0xff); - } - mmc_spi_cs_high(); - mmc_spi_io(0xff); - - return(0); -} - -static void mmc_request(request_queue_t *q) -{ - unsigned int mmc_address; - unsigned char *buffer_address; - int nr_sectors; - int i; - int cmd; - int rc, code; - - (void)q; - while (1) - { - code = 1; // Default is success - INIT_REQUEST; - mmc_address = (CURRENT->sector + hd[MINOR(CURRENT->rq_dev)].start_sect) * hd_hardsectsizes[0]; - buffer_address = CURRENT->buffer; - nr_sectors = CURRENT->current_nr_sectors; - cmd = CURRENT->cmd; - if (((CURRENT->sector + CURRENT->current_nr_sectors + hd[MINOR(CURRENT->rq_dev)].start_sect) > hd[0].nr_sects) || (mmc_media_detect == 0)) - { - code = 0; - } - else if (cmd == READ) - { - spin_unlock_irq(&io_request_lock); - for (i = 0; i < nr_sectors; i++) - { - rc = mmc_read_block(buffer_address, mmc_address); - if (rc != 0) - { - printk("mmc: error in mmc_read_block (%d)\n", rc); - code = 0; - break; - } - else - { - mmc_address += hd_hardsectsizes[0]; - buffer_address += hd_hardsectsizes[0]; - } - } - spin_lock_irq(&io_request_lock); - } - else if (cmd == WRITE) - { - spin_unlock_irq(&io_request_lock); - for (i = 0; i < nr_sectors; i++) - { - rc = mmc_write_block(mmc_address, buffer_address); - if (rc != 0) - { - printk("mmc: error in mmc_write_block (%d)\n", rc); - code = 0; - break; - } - else - { - mmc_address += hd_hardsectsizes[0]; - buffer_address += hd_hardsectsizes[0]; - } - } - spin_lock_irq(&io_request_lock); - } - else - { - code = 0; - } - end_request(code); - } -} - - -static int mmc_open(struct inode *inode, struct file *filp) -{ - int device; - (void)filp; - - if (mmc_media_detect == 0) return -ENODEV; - -#if defined(MODULE) - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int mmc_release(struct inode *inode, struct file *filp) -{ - (void)filp; - fsync_dev(inode->i_rdev); - invalidate_buffers(inode->i_rdev); - -#if defined(MODULE) - MOD_DEC_USE_COUNT; -#endif - return 0; -} - -extern struct gendisk hd_gendisk; -static int mmc_revalidate(kdev_t dev) -{ - int target, max_p, start, i; - if (mmc_media_detect == 0) return -ENODEV; - - target = DEVICE_NR(dev); - - max_p = hd_gendisk.max_p; - start = target << 6; - for (i = max_p - 1; i >= 0; i--) { - int minor = start + i; - invalidate_device(MKDEV(MAJOR_NR, minor), 1); - hd_gendisk.part[minor].start_sect = 0; - hd_gendisk.part[minor].nr_sects = 0; - } - - grok_partitions(&hd_gendisk, target, 1 << 6, - hd_sizes[0] * 2); - - return 0; -} - -static int mmc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -{ - if (!inode || !inode->i_rdev) - return -EINVAL; - - switch(cmd) { - case BLKGETSIZE: - return put_user(hd[MINOR(inode->i_rdev)].nr_sects, (unsigned long *)arg); - case BLKGETSIZE64: - return put_user((u64)hd[MINOR(inode->i_rdev)]. - nr_sects, (u64 *) arg); - case BLKRRPART: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - return mmc_revalidate(inode->i_rdev); - case HDIO_GETGEO: - { - struct hd_geometry *loc, g; - loc = (struct hd_geometry *) arg; - if (!loc) - return -EINVAL; - g.heads = 4; - g.sectors = 16; - g.cylinders = hd[0].nr_sects / (4 * 16); - g.start = hd[MINOR(inode->i_rdev)].start_sect; - return copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0; - } - default: - return blk_ioctl(inode->i_rdev, cmd, arg); - } -} - -static int mmc_card_init(void) -{ - unsigned char r = 0; - short i, j; - unsigned long flags; - - save_flags(flags); - cli(); - - printk("mmc Card init\n"); - mmc_spi_cs_high(); - for (i = 0; i < 20; i++) mmc_spi_io(0xff); - - mmc_spi_cs_low(); - - mmc_spi_io(0x40); - for (i = 0; i < 4; i++) mmc_spi_io(0x00); - mmc_spi_io(0x95); - for (i = 0; i < 8; i++) - { - r = mmc_spi_io(0xff); - if (r == 0x01) break; - } - mmc_spi_cs_high(); - mmc_spi_io(0xff); - if (r != 0x01) - { - restore_flags(flags); - return(1); - } - - printk("mmc Card init *1*\n"); - for (j = 0; j < 10000; j++) - { - mmc_spi_cs_low(); - - mmc_spi_io(0x41); - for (i = 0; i < 4; i++) mmc_spi_io(0x00); - mmc_spi_io(0xff); - for (i = 0; i < 8; i++) - { - r = mmc_spi_io(0xff); - if (r == 0x00) break; - } - mmc_spi_cs_high(); - mmc_spi_io(0xff); - if (r == 0x00) - { - restore_flags(flags); - printk("mmc Card init *2*\n"); - return(0); - } - } - restore_flags(flags); - - return(2); -} - -static int mmc_card_config(void) -{ - unsigned char r = 0; - short i; - unsigned char csd[32]; - unsigned int c_size; - unsigned int c_size_mult; - unsigned int mult; - unsigned int read_bl_len; - unsigned int blocknr = 0; - unsigned int block_len = 0; - unsigned int size = 0; - - mmc_spi_cs_low(); - for (i = 0; i < 4; i++) mmc_spi_io(0xff); - mmc_spi_io(0x49); - for (i = 0; i < 4; i++) mmc_spi_io(0x00); - mmc_spi_io(0xff); - for (i = 0; i < 8; i++) - { - r = mmc_spi_io(0xff); - if (r == 0x00) break; - } - if (r != 0x00) - { - mmc_spi_cs_high(); - mmc_spi_io(0xff); - return(1); - } - for (i = 0; i < 8; i++) - { - r = mmc_spi_io(0xff); - if (r == 0xfe) break; - } - if (r != 0xfe) - { - mmc_spi_cs_high(); - mmc_spi_io(0xff); - return(2); - } - for (i = 0; i < 16; i++) - { - r = mmc_spi_io(0xff); - csd[i] = r; - } - for (i = 0; i < 2; i++) - { - r = mmc_spi_io(0xff); - } - mmc_spi_cs_high(); - mmc_spi_io(0xff); - if (r == 0x00) return(3); - - c_size = csd[8] + csd[7] * 256 + (csd[6] & 0x03) * 256 * 256; - c_size >>= 6; - c_size_mult = csd[10] + (csd[9] & 0x03) * 256; - c_size_mult >>= 7; - read_bl_len = csd[5] & 0x0f; - mult = 1; - mult <<= c_size_mult + 2; - blocknr = (c_size + 1) * mult; - block_len = 1; - block_len <<= read_bl_len; - size = block_len * blocknr; - size >>= 10; - - for(i=0; i<(1<<6); i++) { - hd_blocksizes[i] = 1024; - hd_hardsectsizes[i] = block_len; - hd_maxsect[i] = 256; - } - hd_sizes[0] = size; - hd[0].nr_sects = blocknr; - - - printk("Size = %d, hardsectsize = %d, sectors = %d\n", - size, block_len, blocknr); - - return 0; -} - -static int mmc_hardware_init(void) -{ - unsigned char gpio_outen; - - // Set inputs/outputs here - printk("mmc Hardware init\n"); - gpio_outen = *gpioaddr_enable; - - gpio_outen = (gpio_outen | SD_DI | SD_CLK | SD_CS) & ~SD_DO; - *gpioaddr_enable = gpio_outen; - - port_state = *gpioaddr_input; - - // Clock low - port_state &= ~(SD_CLK | SD_DI | SD_CS); - *gpioaddr_output = port_state; - - return 0; -} - -static int mmc_check_media_change(kdev_t dev) -{ - (void)dev; - if (mmc_media_changed == 1) - { - mmc_media_changed = 0; - return 1; - } - else return 0; -} - -static struct block_device_operations mmc_bdops = -{ - open: mmc_open, - release: mmc_release, - ioctl: mmc_ioctl, -#if 0 - check_media_change: mmc_check_media_change, - revalidate: mmc_revalidate, -#endif -}; - -static struct gendisk hd_gendisk = { - major: MAJOR_NR, - major_name: DEVICE_NAME, - minor_shift: 6, - max_p: 1 << 6, - part: hd, - sizes: hd_sizes, - fops: &mmc_bdops, -}; - -static int mmc_init(void) -{ - int rc; - - rc = mmc_hardware_init(); - - if ( rc != 0) - { - printk("mmc: error in mmc_hardware_init (%d)\n", rc); - return -1; - } - - rc = mmc_card_init(); - if ( rc != 0) - { - // Give it an extra shot - rc = mmc_card_init(); - if ( rc != 0) - { - printk("mmc: error in mmc_card_init (%d)\n", rc); - return -1; - } - } - - memset(hd_sizes, 0, sizeof(hd_sizes)); - rc = mmc_card_config(); - if ( rc != 0) - { - printk("mmc: error in mmc_card_config (%d)\n", rc); - return -1; - } - - - blk_size[MAJOR_NR] = hd_sizes; - - memset(hd, 0, sizeof(hd)); - hd[0].nr_sects = hd_sizes[0]*2; - - blksize_size[MAJOR_NR] = hd_blocksizes; - hardsect_size[MAJOR_NR] = hd_hardsectsizes; - max_sectors[MAJOR_NR] = hd_maxsect; - - hd_gendisk.nr_real = 1; - - register_disk(&hd_gendisk, MKDEV(MAJOR_NR,0), 1<<6, - &mmc_bdops, hd_sizes[0]*2); - - return 0; -} - -static void mmc_exit(void) -{ - blk_size[MAJOR_NR] = NULL; - blksize_size[MAJOR_NR] = NULL; - hardsect_size[MAJOR_NR] = NULL; - max_sectors[MAJOR_NR] = NULL; - hd[0].nr_sects = 0; -} - -static void mmc_check_media(void) -{ - int old_state; - int rc; - - old_state = mmc_media_detect; - - // TODO: Add card detection here - mmc_media_detect = 1; - if (old_state != mmc_media_detect) - { - mmc_media_changed = 1; - if (mmc_media_detect == 1) - { - rc = mmc_init(); - if (rc != 0) printk("mmc: error in mmc_init (%d)\n", rc); - } - else - { - mmc_exit(); - } - } - - /* del_timer(&mmc_timer); - mmc_timer.expires = jiffies + 10*HZ; - add_timer(&mmc_timer); */ -} - -static int __init mmc_driver_init(void) -{ - int rc; - - rc = devfs_register_blkdev(MAJOR_NR, DEVICE_NAME, &mmc_bdops); - if (rc < 0) - { - printk(KERN_WARNING "mmc: can't get major %d\n", MAJOR_NR); - return rc; - } - - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), mmc_request); - - read_ahead[MAJOR_NR] = 8; - add_gendisk(&hd_gendisk); - - mmc_check_media(); - - /*init_timer(&mmc_timer); - mmc_timer.expires = jiffies + HZ; - mmc_timer.function = (void *)mmc_check_media; - add_timer(&mmc_timer);*/ - - return 0; -} - -static void __exit mmc_driver_exit(void) -{ - int i; - del_timer(&mmc_timer); - - for (i = 0; i < (1 << 6); i++) - fsync_dev(MKDEV(MAJOR_NR, i)); - - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - del_gendisk(&hd_gendisk); - devfs_unregister_blkdev(MAJOR_NR, DEVICE_NAME); - mmc_exit(); -} - -module_init(mmc_driver_init); -module_exit(mmc_driver_exit); |