diff options
Diffstat (limited to 'arch/xtensa/platforms')
| -rw-r--r-- | arch/xtensa/platforms/iss/Makefile | 4 | ||||
| -rw-r--r-- | arch/xtensa/platforms/iss/console.c | 22 | ||||
| -rw-r--r-- | arch/xtensa/platforms/iss/include/platform/simcall.h | 24 | ||||
| -rw-r--r-- | arch/xtensa/platforms/iss/network.c | 306 | ||||
| -rw-r--r-- | arch/xtensa/platforms/iss/setup.c | 8 | ||||
| -rw-r--r-- | arch/xtensa/platforms/iss/simdisk.c | 384 | ||||
| -rw-r--r-- | arch/xtensa/platforms/xt2000/setup.c | 14 | ||||
| -rw-r--r-- | arch/xtensa/platforms/xtfpga/include/platform/hardware.h | 6 | ||||
| -rw-r--r-- | arch/xtensa/platforms/xtfpga/setup.c | 32 |
9 files changed, 540 insertions, 260 deletions
diff --git a/arch/xtensa/platforms/iss/Makefile b/arch/xtensa/platforms/iss/Makefile index b7d1a5c0ff7..b3e89291cfb 100644 --- a/arch/xtensa/platforms/iss/Makefile +++ b/arch/xtensa/platforms/iss/Makefile @@ -4,5 +4,7 @@ # "prom monitor" library routines under Linux. # -obj-y = console.o setup.o +obj-y = setup.o +obj-$(CONFIG_TTY) += console.o obj-$(CONFIG_NET) += network.o +obj-$(CONFIG_BLK_DEV_SIMDISK) += simdisk.o diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 8207a119eee..70cb408bc20 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -56,12 +56,13 @@ static void rs_poll(unsigned long); static int rs_open(struct tty_struct *tty, struct file * filp) { tty->port = &serial_port; - spin_lock(&timer_lock); + spin_lock_bh(&timer_lock); if (tty->count == 1) { - setup_timer(&serial_timer, rs_poll, (unsigned long)tty); + setup_timer(&serial_timer, rs_poll, + (unsigned long)&serial_port); mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE); } - spin_unlock(&timer_lock); + spin_unlock_bh(&timer_lock); return 0; } @@ -97,22 +98,20 @@ static int rs_write(struct tty_struct * tty, static void rs_poll(unsigned long priv) { - struct tty_struct* tty = (struct tty_struct*) priv; - - struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; + struct tty_port *port = (struct tty_port *)priv; int i = 0; unsigned char c; spin_lock(&timer_lock); - while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){ - __simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0); - tty_insert_flip_char(tty, c, TTY_NORMAL); + while (simc_poll(0)) { + simc_read(0, &c, 1); + tty_insert_flip_char(port, c, TTY_NORMAL); i++; } if (i) - tty_flip_buffer_push(tty); + tty_flip_buffer_push(port); mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE); @@ -244,8 +243,7 @@ static void iss_console_write(struct console *co, const char *s, unsigned count) int len = strlen(s); if (s != 0 && *s != 0) - __simc (SYS_write, 1, (unsigned long)s, - count < len ? count : len,0,0); + simc_write(1, s, count < len ? count : len); } static struct tty_driver* iss_console_device(struct console *c, int *index) diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h index b5a4edf02d7..12b15ad1e58 100644 --- a/arch/xtensa/platforms/iss/include/platform/simcall.h +++ b/arch/xtensa/platforms/iss/include/platform/simcall.h @@ -59,56 +59,58 @@ static int errno; -static inline int __simc(int a, int b, int c, int d, int e, int f) +static inline int __simc(int a, int b, int c, int d) { int ret; register int a1 asm("a2") = a; register int b1 asm("a3") = b; register int c1 asm("a4") = c; register int d1 asm("a5") = d; - register int e1 asm("a6") = e; - register int f1 asm("a7") = f; __asm__ __volatile__ ( "simcall\n" "mov %0, a2\n" "mov %1, a3\n" : "=a" (ret), "=a" (errno), "+r"(a1), "+r"(b1) - : "r"(c1), "r"(d1), "r"(e1), "r"(f1) + : "r"(c1), "r"(d1) : "memory"); return ret; } static inline int simc_open(const char *file, int flags, int mode) { - return __simc(SYS_open, (int) file, flags, mode, 0, 0); + return __simc(SYS_open, (int) file, flags, mode); } static inline int simc_close(int fd) { - return __simc(SYS_close, fd, 0, 0, 0, 0); + return __simc(SYS_close, fd, 0, 0); } static inline int simc_ioctl(int fd, int request, void *arg) { - return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0); + return __simc(SYS_ioctl, fd, request, (int) arg); } static inline int simc_read(int fd, void *buf, size_t count) { - return __simc(SYS_read, fd, (int) buf, count, 0, 0); + return __simc(SYS_read, fd, (int) buf, count); } static inline int simc_write(int fd, const void *buf, size_t count) { - return __simc(SYS_write, fd, (int) buf, count, 0, 0); + return __simc(SYS_write, fd, (int) buf, count); } static inline int simc_poll(int fd) { struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; - return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv, - 0, 0); + return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv); +} + +static inline int simc_lseek(int fd, uint32_t off, int whence) +{ + return __simc(SYS_lseek, fd, off, whence); } #endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */ diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 7d0fea6d7f2..d05f8feeb8d 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -38,7 +38,7 @@ #define DRIVER_NAME "iss-netdev" #define ETH_MAX_PACKET 1500 #define ETH_HEADER_OTHER 14 -#define ISS_NET_TIMER_VALUE (2 * HZ) +#define ISS_NET_TIMER_VALUE (HZ / 10) static DEFINE_SPINLOCK(opened_lock); @@ -56,8 +56,6 @@ static LIST_HEAD(devices); struct tuntap_info { char dev_name[IFNAMSIZ]; - int fixed_config; - unsigned char gw[ETH_ALEN]; int fd; }; @@ -67,7 +65,6 @@ struct tuntap_info { /* This structure contains out private information for the driver. */ struct iss_net_private { - struct list_head device_list; struct list_head opened_list; @@ -83,9 +80,6 @@ struct iss_net_private { int index; int mtu; - unsigned char mac[ETH_ALEN]; - int have_mac; - struct { union { struct tuntap_info tuntap; @@ -118,68 +112,48 @@ static char *split_if_spec(char *str, ...) *arg = str; if (end == NULL) return NULL; - *end ++ = '\0'; + *end++ = '\0'; str = end; } va_end(ap); return str; } +/* Set Ethernet address of the specified device. */ -#if 0 -/* Adjust SKB. */ - -struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) +static void setup_etheraddr(struct net_device *dev, char *str) { - if ((skb != NULL) && (skb_tailroom(skb) < extra)) { - struct sk_buff *skb2; - - skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC); - dev_kfree_skb(skb); - skb = skb2; - } - if (skb != NULL) - skb_put(skb, extra); - - return skb; -} -#endif + unsigned char *addr = dev->dev_addr; -/* Return the IP address as a string for a given device. */ + if (str == NULL) + goto random; -static void dev_ip_addr(void *d, char *buf, char *bin_buf) -{ - struct net_device *dev = d; - struct in_device *ip = dev->ip_ptr; - struct in_ifaddr *in; - __be32 addr; - - if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) { - printk(KERN_WARNING "Device not assigned an IP address!\n"); - return; + if (!mac_pton(str, addr)) { + pr_err("%s: failed to parse '%s' as an ethernet address\n", + dev->name, str); + goto random; } - - addr = in->ifa_address; - sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff, - (addr >> 16) & 0xff, addr >> 24); - - if (bin_buf) { - bin_buf[0] = addr & 0xff; - bin_buf[1] = (addr >> 8) & 0xff; - bin_buf[2] = (addr >> 16) & 0xff; - bin_buf[3] = addr >> 24; + if (is_multicast_ether_addr(addr)) { + pr_err("%s: attempt to assign a multicast ethernet address\n", + dev->name); + goto random; } + if (!is_valid_ether_addr(addr)) { + pr_err("%s: attempt to assign an invalid ethernet address\n", + dev->name); + goto random; + } + if (!is_local_ether_addr(addr)) + pr_warn("%s: assigning a globally valid ethernet address\n", + dev->name); + return; + +random: + pr_info("%s: choosing a random ethernet address\n", + dev->name); + eth_hw_addr_random(dev); } -/* Set Ethernet address of the specified device. */ - -static void inline set_ether_mac(void *d, unsigned char *addr) -{ - struct net_device *dev = d; - memcpy(dev->dev_addr, addr, ETH_ALEN); -} - - /* ======================= TUNTAP TRANSPORT INTERFACE ====================== */ static int tuntap_open(struct iss_net_private *lp) @@ -189,24 +163,21 @@ static int tuntap_open(struct iss_net_private *lp) int err = -EINVAL; int fd; - /* We currently only support a fixed configuration. */ - - if (!lp->tp.info.tuntap.fixed_config) - return -EINVAL; - - if ((fd = simc_open("/dev/net/tun", 02, 0)) < 0) { /* O_RDWR */ - printk("Failed to open /dev/net/tun, returned %d " - "(errno = %d)\n", fd, errno); + fd = simc_open("/dev/net/tun", 02, 0); /* O_RDWR */ + if (fd < 0) { + pr_err("%s: failed to open /dev/net/tun, returned %d (errno = %d)\n", + lp->dev->name, fd, errno); return fd; } - memset(&ifr, 0, sizeof ifr); + memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name); + strlcpy(ifr.ifr_name, dev_name, sizeof(ifr.ifr_name)); - if ((err = simc_ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0) { - printk("Failed to set interface, returned %d " - "(errno = %d)\n", err, errno); + err = simc_ioctl(fd, TUNSETIFF, &ifr); + if (err < 0) { + pr_err("%s: failed to set interface %s, returned %d (errno = %d)\n", + lp->dev->name, dev_name, err, errno); simc_close(fd); return err; } @@ -217,27 +188,17 @@ static int tuntap_open(struct iss_net_private *lp) static void tuntap_close(struct iss_net_private *lp) { -#if 0 - if (lp->tp.info.tuntap.fixed_config) - iter_addresses(lp->tp.info.tuntap.dev, close_addr, lp->host.dev_name); -#endif simc_close(lp->tp.info.tuntap.fd); lp->tp.info.tuntap.fd = -1; } -static int tuntap_read (struct iss_net_private *lp, struct sk_buff **skb) +static int tuntap_read(struct iss_net_private *lp, struct sk_buff **skb) { -#if 0 - *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); - if (*skb == NULL) - return -ENOMEM; -#endif - return simc_read(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER); } -static int tuntap_write (struct iss_net_private *lp, struct sk_buff **skb) +static int tuntap_write(struct iss_net_private *lp, struct sk_buff **skb) { return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len); } @@ -253,45 +214,45 @@ static int tuntap_poll(struct iss_net_private *lp) } /* - * Currently only a device name is supported. - * ethX=tuntap[,[mac address][,[device name]]] + * ethX=tuntap,[mac address],device name */ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) { - const int len = strlen(TRANSPORT_TUNTAP_NAME); + struct net_device *dev = lp->dev; char *dev_name = NULL, *mac_str = NULL, *rem = NULL; /* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */ - if (strncmp(init, TRANSPORT_TUNTAP_NAME, len)) + if (strncmp(init, TRANSPORT_TUNTAP_NAME, + sizeof(TRANSPORT_TUNTAP_NAME) - 1)) return 0; - if (*(init += strlen(TRANSPORT_TUNTAP_NAME)) == ',') { - if ((rem=split_if_spec(init+1, &mac_str, &dev_name)) != NULL) { - printk("Extra garbage on specification : '%s'\n", rem); + init += sizeof(TRANSPORT_TUNTAP_NAME) - 1; + if (*init == ',') { + rem = split_if_spec(init + 1, &mac_str, &dev_name); + if (rem != NULL) { + pr_err("%s: extra garbage on specification : '%s'\n", + dev->name, rem); return 0; } } else if (*init != '\0') { - printk("Invalid argument: %s. Skipping device!\n", init); + pr_err("%s: invalid argument: %s. Skipping device!\n", + dev->name, init); return 0; } - if (dev_name) { - strncpy(lp->tp.info.tuntap.dev_name, dev_name, - sizeof lp->tp.info.tuntap.dev_name); - lp->tp.info.tuntap.fixed_config = 1; - } else - strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME); + if (!dev_name) { + pr_err("%s: missing tuntap device name\n", dev->name); + return 0; + } + strlcpy(lp->tp.info.tuntap.dev_name, dev_name, + sizeof(lp->tp.info.tuntap.dev_name)); -#if 0 - if (setup_etheraddr(mac_str, lp->mac)) - lp->have_mac = 1; -#endif - lp->mtu = TRANSPORT_TUNTAP_MTU; + setup_etheraddr(dev, mac_str); - //lp->info.tuntap.gate_addr = gate_addr; + lp->mtu = TRANSPORT_TUNTAP_MTU; lp->tp.info.tuntap.fd = -1; @@ -302,13 +263,6 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) lp->tp.protocol = tuntap_protocol; lp->tp.poll = tuntap_poll; - printk("TUN/TAP backend - "); -#if 0 - if (lp->host.gate_addr != NULL) - printk("IP = %s", lp->host.gate_addr); -#endif - printk("\n"); - return 1; } @@ -327,7 +281,8 @@ static int iss_net_rx(struct net_device *dev) /* Try to allocate memory, if it fails, try again next round. */ - if ((skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER)) == NULL) { + skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER); + if (skb == NULL) { lp->stats.rx_dropped++; return 0; } @@ -347,7 +302,6 @@ static int iss_net_rx(struct net_device *dev) lp->stats.rx_bytes += skb->len; lp->stats.rx_packets++; - // netif_rx(skb); netif_rx_ni(skb); return pkt_len; } @@ -378,11 +332,11 @@ static int iss_net_poll(void) spin_unlock(&lp->lock); if (err < 0) { - printk(KERN_ERR "Device '%s' read returned %d, " - "shutting it down\n", lp->dev->name, err); + pr_err("Device '%s' read returned %d, shutting it down\n", + lp->dev->name, err); dev_close(lp->dev); } else { - // FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ); + /* FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ); */ } } @@ -393,14 +347,11 @@ static int iss_net_poll(void) static void iss_net_timer(unsigned long priv) { - struct iss_net_private* lp = (struct iss_net_private*) priv; + struct iss_net_private *lp = (struct iss_net_private *)priv; spin_lock(&lp->lock); - iss_net_poll(); - mod_timer(&lp->timer, jiffies + lp->timer_val); - spin_unlock(&lp->lock); } @@ -408,19 +359,14 @@ static void iss_net_timer(unsigned long priv) static int iss_net_open(struct net_device *dev) { struct iss_net_private *lp = netdev_priv(dev); - char addr[sizeof "255.255.255.255\0"]; int err; spin_lock(&lp->lock); - if ((err = lp->tp.open(lp)) < 0) + err = lp->tp.open(lp); + if (err < 0) goto out; - if (!lp->have_mac) { - dev_ip_addr(dev, addr, &lp->mac[2]); - set_ether_mac(dev, lp->mac); - } - netif_start_queue(dev); /* clear buffer - it can happen that the host side of the interface @@ -448,7 +394,6 @@ out: static int iss_net_close(struct net_device *dev) { struct iss_net_private *lp = netdev_priv(dev); -printk("iss_net_close!\n"); netif_stop_queue(dev); spin_lock(&lp->lock); @@ -490,7 +435,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev) } else { netif_start_queue(dev); - printk(KERN_ERR "iss_net_start_xmit: failed(%d)\n", len); + pr_err("%s: %s failed(%d)\n", dev->name, __func__, len); } spin_unlock_irqrestore(&lp->lock, flags); @@ -508,56 +453,27 @@ static struct net_device_stats *iss_net_get_stats(struct net_device *dev) static void iss_net_set_multicast_list(struct net_device *dev) { -#if 0 - if (dev->flags & IFF_PROMISC) - return; - else if (!netdev_mc_empty(dev)) - dev->flags |= IFF_ALLMULTI; - else - dev->flags &= ~IFF_ALLMULTI; -#endif } static void iss_net_tx_timeout(struct net_device *dev) { -#if 0 - dev->trans_start = jiffies; - netif_wake_queue(dev); -#endif } static int iss_net_set_mac(struct net_device *dev, void *addr) { -#if 0 struct iss_net_private *lp = netdev_priv(dev); struct sockaddr *hwaddr = addr; + if (!is_valid_ether_addr(hwaddr->sa_data)) + return -EADDRNOTAVAIL; spin_lock(&lp->lock); memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); spin_unlock(&lp->lock); -#endif - return 0; } static int iss_net_change_mtu(struct net_device *dev, int new_mtu) { -#if 0 - struct iss_net_private *lp = netdev_priv(dev); - int err = 0; - - spin_lock(&lp->lock); - - // FIXME not needed new_mtu = transport_set_mtu(new_mtu, &lp->user); - - if (new_mtu < 0) - err = new_mtu; - else - dev->mtu = new_mtu; - - spin_unlock(&lp->lock); - return err; -#endif return -EINVAL; } @@ -582,7 +498,6 @@ static const struct net_device_ops iss_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = iss_net_change_mtu, .ndo_set_mac_address = iss_net_set_mac, - //.ndo_do_ioctl = iss_net_ioctl, .ndo_tx_timeout = iss_net_tx_timeout, .ndo_set_rx_mode = iss_net_set_multicast_list, }; @@ -593,24 +508,29 @@ static int iss_net_configure(int index, char *init) struct iss_net_private *lp; int err; - if ((dev = alloc_etherdev(sizeof *lp)) == NULL) { - printk(KERN_ERR "eth_configure: failed to allocate device\n"); + dev = alloc_etherdev(sizeof(*lp)); + if (dev == NULL) { + pr_err("eth_configure: failed to allocate device\n"); return 1; } /* Initialize private element. */ lp = netdev_priv(dev); - *lp = ((struct iss_net_private) { + *lp = (struct iss_net_private) { .device_list = LIST_HEAD_INIT(lp->device_list), .opened_list = LIST_HEAD_INIT(lp->opened_list), .lock = __SPIN_LOCK_UNLOCKED(lp.lock), .dev = dev, .index = index, - //.fd = -1, - .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 }, - .have_mac = 0, - }); + }; + + /* + * If this name ends up conflicting with an existing registered + * netdevice, that is OK, register_netdev{,ice}() will notice this + * and fail. + */ + snprintf(dev->name, sizeof(dev->name), "eth%d", index); /* * Try all transport protocols. @@ -618,14 +538,12 @@ static int iss_net_configure(int index, char *init) */ if (!tuntap_probe(lp, index, init)) { - printk("Invalid arguments. Skipping device!\n"); + pr_err("%s: invalid arguments. Skipping device!\n", + dev->name); goto errout; } - printk(KERN_INFO "Netdevice %d ", index); - if (lp->have_mac) - printk("(%pM) ", lp->mac); - printk(": "); + pr_info("Netdevice %d (%pM)\n", index, dev->dev_addr); /* sysfs register */ @@ -641,14 +559,7 @@ static int iss_net_configure(int index, char *init) lp->pdev.id = index; lp->pdev.name = DRIVER_NAME; platform_device_register(&lp->pdev); - SET_NETDEV_DEV(dev,&lp->pdev.dev); - - /* - * If this name ends up conflicting with an existing registered - * netdevice, that is OK, register_netdev{,ice}() will notice this - * and fail. - */ - snprintf(dev->name, sizeof dev->name, "eth%d", index); + SET_NETDEV_DEV(dev, &lp->pdev.dev); dev->netdev_ops = &iss_netdev_ops; dev->mtu = lp->mtu; @@ -660,7 +571,7 @@ static int iss_net_configure(int index, char *init) rtnl_unlock(); if (err) { - printk("Error registering net device!\n"); + pr_err("%s: error registering net device!\n", dev->name); /* XXX: should we call ->remove() here? */ free_netdev(dev); return 1; @@ -669,16 +580,11 @@ static int iss_net_configure(int index, char *init) init_timer(&lp->tl); lp->tl.function = iss_net_user_timer_expire; -#if 0 - if (lp->have_mac) - set_ether_mac(dev, lp->mac); -#endif return 0; errout: - // FIXME: unregister; free, etc.. + /* FIXME: unregister; free, etc.. */ return -EIO; - } /* ------------------------------------------------------------------------- */ @@ -700,27 +606,28 @@ struct iss_net_init { #define ERR KERN_ERR "iss_net_setup: " -static int iss_net_setup(char *str) +static int __init iss_net_setup(char *str) { struct iss_net_private *device = NULL; struct iss_net_init *new; struct list_head *ele; char *end; - int n; + int rc; + unsigned n; - n = simple_strtoul(str, &end, 0); - if (end == str) { - printk(ERR "Failed to parse '%s'\n", str); - return 1; - } - if (n < 0) { - printk(ERR "Device %d is negative\n", n); + end = strchr(str, '='); + if (!end) { + printk(ERR "Expected '=' after device number\n"); return 1; } - if (*(str = end) != '=') { - printk(ERR "Expected '=' after device number\n"); + *end = 0; + rc = kstrtouint(str, 0, &n); + *end = '='; + if (rc < 0) { + printk(ERR "Failed to parse '%s'\n", str); return 1; } + str = end; spin_lock(&devices_lock); @@ -733,12 +640,13 @@ static int iss_net_setup(char *str) spin_unlock(&devices_lock); if (device && device->index == n) { - printk(ERR "Device %d already configured\n", n); + printk(ERR "Device %u already configured\n", n); return 1; } - if ((new = alloc_bootmem(sizeof new)) == NULL) { - printk("Alloc_bootmem failed\n"); + new = alloc_bootmem(sizeof(*new)); + if (new == NULL) { + printk(ERR "Alloc_bootmem failed\n"); return 1; } @@ -752,7 +660,7 @@ static int iss_net_setup(char *str) #undef ERR -__setup("eth=", iss_net_setup); +__setup("eth", iss_net_setup); /* * Initialize all ISS Ethernet devices previously registered in iss_net_setup. diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c index e1700102f35..da7d1824086 100644 --- a/arch/xtensa/platforms/iss/setup.c +++ b/arch/xtensa/platforms/iss/setup.c @@ -38,12 +38,6 @@ void __init platform_init(bp_tag_t* bootparam) } -#ifdef CONFIG_PCI -void platform_pcibios_init(void) -{ -} -#endif - void platform_halt(void) { pr_info(" ** Called platform_halt() **\n"); @@ -64,7 +58,9 @@ void platform_restart(void) "wsr a2, icountlevel\n\t" "movi a2, 0\n\t" "wsr a2, icount\n\t" +#if XCHAL_NUM_IBREAK > 0 "wsr a2, ibreakenable\n\t" +#endif "wsr a2, lcount\n\t" "movi a2, 0x1f\n\t" "wsr a2, ps\n\t" diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c new file mode 100644 index 00000000000..48eebacdf5f --- /dev/null +++ b/arch/xtensa/platforms/iss/simdisk.c @@ -0,0 +1,384 @@ +/* + * arch/xtensa/platforms/iss/simdisk.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001-2013 Tensilica Inc. + * Authors Victor Prupis + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/blkdev.h> +#include <linux/bio.h> +#include <linux/proc_fs.h> +#include <asm/uaccess.h> +#include <platform/simcall.h> + +#define SIMDISK_MAJOR 240 +#define SECTOR_SHIFT 9 +#define SIMDISK_MINORS 1 +#define MAX_SIMDISK_COUNT 10 + +struct simdisk { + const char *filename; + spinlock_t lock; + struct request_queue *queue; + struct gendisk *gd; + struct proc_dir_entry *procfile; + int users; + unsigned long size; + int fd; +}; + + +static int simdisk_count = CONFIG_BLK_DEV_SIMDISK_COUNT; +module_param(simdisk_count, int, S_IRUGO); +MODULE_PARM_DESC(simdisk_count, "Number of simdisk units."); + +static int n_files; +static const char *filename[MAX_SIMDISK_COUNT] = { +#ifdef CONFIG_SIMDISK0_FILENAME + CONFIG_SIMDISK0_FILENAME, +#ifdef CONFIG_SIMDISK1_FILENAME + CONFIG_SIMDISK1_FILENAME, +#endif +#endif +}; + +static int simdisk_param_set_filename(const char *val, + const struct kernel_param *kp) +{ + if (n_files < ARRAY_SIZE(filename)) + filename[n_files++] = val; + else + return -EINVAL; + return 0; +} + +static const struct kernel_param_ops simdisk_param_ops_filename = { + .set = simdisk_param_set_filename, +}; +module_param_cb(filename, &simdisk_param_ops_filename, &n_files, 0); +MODULE_PARM_DESC(filename, "Backing storage filename."); + +static int simdisk_major = SIMDISK_MAJOR; + +static void simdisk_transfer(struct simdisk *dev, unsigned long sector, + unsigned long nsect, char *buffer, int write) +{ + unsigned long offset = sector << SECTOR_SHIFT; + unsigned long nbytes = nsect << SECTOR_SHIFT; + + if (offset > dev->size || dev->size - offset < nbytes) { + pr_notice("Beyond-end %s (%ld %ld)\n", + write ? "write" : "read", offset, nbytes); + return; + } + + spin_lock(&dev->lock); + while (nbytes > 0) { + unsigned long io; + + simc_lseek(dev->fd, offset, SEEK_SET); + if (write) + io = simc_write(dev->fd, buffer, nbytes); + else + io = simc_read(dev->fd, buffer, nbytes); + if (io == -1) { + pr_err("SIMDISK: IO error %d\n", errno); + break; + } + buffer += io; + offset += io; + nbytes -= io; + } + spin_unlock(&dev->lock); +} + +static int simdisk_xfer_bio(struct simdisk *dev, struct bio *bio) +{ + struct bio_vec bvec; + struct bvec_iter iter; + sector_t sector = bio->bi_iter.bi_sector; + + bio_for_each_segment(bvec, bio, iter) { + char *buffer = __bio_kmap_atomic(bio, iter); + unsigned len = bvec.bv_len >> SECTOR_SHIFT; + + simdisk_transfer(dev, sector, len, buffer, + bio_data_dir(bio) == WRITE); + sector += len; + __bio_kunmap_atomic(buffer); + } + return 0; +} + +static void simdisk_make_request(struct request_queue *q, struct bio *bio) +{ + struct simdisk *dev = q->queuedata; + int status = simdisk_xfer_bio(dev, bio); + bio_endio(bio, status); +} + + +static int simdisk_open(struct block_device *bdev, fmode_t mode) +{ + struct simdisk *dev = bdev->bd_disk->private_data; + + spin_lock(&dev->lock); + if (!dev->users) + check_disk_change(bdev); + ++dev->users; + spin_unlock(&dev->lock); + return 0; +} + +static void simdisk_release(struct gendisk *disk, fmode_t mode) +{ + struct simdisk *dev = disk->private_data; + spin_lock(&dev->lock); + --dev->users; + spin_unlock(&dev->lock); +} + +static const struct block_device_operations simdisk_ops = { + .owner = THIS_MODULE, + .open = simdisk_open, + .release = simdisk_release, +}; + +static struct simdisk *sddev; +static struct proc_dir_entry *simdisk_procdir; + +static int simdisk_attach(struct simdisk *dev, const char *filename) +{ + int err = 0; + + filename = kstrdup(filename, GFP_KERNEL); + if (filename == NULL) + return -ENOMEM; + + spin_lock(&dev->lock); + + if (dev->fd != -1) { + err = -EBUSY; + goto out; + } + dev->fd = simc_open(filename, O_RDWR, 0); + if (dev->fd == -1) { + pr_err("SIMDISK: Can't open %s: %d\n", filename, errno); + err = -ENODEV; + goto out; + } + dev->size = simc_lseek(dev->fd, 0, SEEK_END); + set_capacity(dev->gd, dev->size >> SECTOR_SHIFT); + dev->filename = filename; + pr_info("SIMDISK: %s=%s\n", dev->gd->disk_name, dev->filename); +out: + if (err) + kfree(filename); + spin_unlock(&dev->lock); + + return err; +} + +static int simdisk_detach(struct simdisk *dev) +{ + int err = 0; + + spin_lock(&dev->lock); + + if (dev->users != 0) { + err = -EBUSY; + } else if (dev->fd != -1) { + if (simc_close(dev->fd)) { + pr_err("SIMDISK: error closing %s: %d\n", + dev->filename, errno); + err = -EIO; + } else { + pr_info("SIMDISK: %s detached from %s\n", + dev->gd->disk_name, dev->filename); + dev->fd = -1; + kfree(dev->filename); + dev->filename = NULL; + } + } + spin_unlock(&dev->lock); + return err; +} + +static ssize_t proc_read_simdisk(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + struct simdisk *dev = PDE_DATA(file_inode(file)); + const char *s = dev->filename; + if (s) { + ssize_t n = simple_read_from_buffer(buf, size, ppos, + s, strlen(s)); + if (n < 0) + return n; + buf += n; + size -= n; + } + return simple_read_from_buffer(buf, size, ppos, "\n", 1); +} + +static ssize_t proc_write_simdisk(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + char *tmp = kmalloc(count + 1, GFP_KERNEL); + struct simdisk *dev = PDE_DATA(file_inode(file)); + int err; + + if (tmp == NULL) + return -ENOMEM; + if (copy_from_user(tmp, buf, count)) { + err = -EFAULT; + goto out_free; + } + + err = simdisk_detach(dev); + if (err != 0) + goto out_free; + + if (count > 0 && tmp[count - 1] == '\n') + tmp[count - 1] = 0; + else + tmp[count] = 0; + + if (tmp[0]) + err = simdisk_attach(dev, tmp); + + if (err == 0) + err = count; +out_free: + kfree(tmp); + return err; +} + +static const struct file_operations fops = { + .read = proc_read_simdisk, + .write = proc_write_simdisk, + .llseek = default_llseek, +}; + +static int __init simdisk_setup(struct simdisk *dev, int which, + struct proc_dir_entry *procdir) +{ + char tmp[2] = { '0' + which, 0 }; + + dev->fd = -1; + dev->filename = NULL; + spin_lock_init(&dev->lock); + dev->users = 0; + + dev->queue = blk_alloc_queue(GFP_KERNEL); + if (dev->queue == NULL) { + pr_err("blk_alloc_queue failed\n"); + goto out_alloc_queue; + } + + blk_queue_make_request(dev->queue, simdisk_make_request); + dev->queue->queuedata = dev; + + dev->gd = alloc_disk(SIMDISK_MINORS); + if (dev->gd == NULL) { + pr_err("alloc_disk failed\n"); + goto out_alloc_disk; + } + dev->gd->major = simdisk_major; + dev->gd->first_minor = which; + dev->gd->fops = &simdisk_ops; + dev->gd->queue = dev->queue; + dev->gd->private_data = dev; + snprintf(dev->gd->disk_name, 32, "simdisk%d", which); + set_capacity(dev->gd, 0); + add_disk(dev->gd); + + dev->procfile = proc_create_data(tmp, 0644, procdir, &fops, dev); + return 0; + +out_alloc_disk: + blk_cleanup_queue(dev->queue); + dev->queue = NULL; +out_alloc_queue: + simc_close(dev->fd); + return -EIO; +} + +static int __init simdisk_init(void) +{ + int i; + + if (register_blkdev(simdisk_major, "simdisk") < 0) { + pr_err("SIMDISK: register_blkdev: %d\n", simdisk_major); + return -EIO; + } + pr_info("SIMDISK: major: %d\n", simdisk_major); + + if (n_files > simdisk_count) + simdisk_count = n_files; + if (simdisk_count > MAX_SIMDISK_COUNT) + simdisk_count = MAX_SIMDISK_COUNT; + + sddev = kmalloc(simdisk_count * sizeof(struct simdisk), + GFP_KERNEL); + if (sddev == NULL) + goto out_unregister; + + simdisk_procdir = proc_mkdir("simdisk", 0); + if (simdisk_procdir == NULL) + goto out_free_unregister; + + for (i = 0; i < simdisk_count; ++i) { + if (simdisk_setup(sddev + i, i, simdisk_procdir) == 0) { + if (filename[i] != NULL && filename[i][0] != 0 && + (n_files == 0 || i < n_files)) + simdisk_attach(sddev + i, filename[i]); + } + } + + return 0; + +out_free_unregister: + kfree(sddev); +out_unregister: + unregister_blkdev(simdisk_major, "simdisk"); + return -ENOMEM; +} +module_init(simdisk_init); + +static void simdisk_teardown(struct simdisk *dev, int which, + struct proc_dir_entry *procdir) +{ + char tmp[2] = { '0' + which, 0 }; + + simdisk_detach(dev); + if (dev->gd) + del_gendisk(dev->gd); + if (dev->queue) + blk_cleanup_queue(dev->queue); + remove_proc_entry(tmp, procdir); +} + +static void __exit simdisk_exit(void) +{ + int i; + + for (i = 0; i < simdisk_count; ++i) + simdisk_teardown(sddev + i, i, simdisk_procdir); + remove_proc_entry("simdisk", 0); + kfree(sddev); + unregister_blkdev(simdisk_major, "simdisk"); +} +module_exit(simdisk_exit); + +MODULE_ALIAS_BLOCKDEV_MAJOR(SIMDISK_MAJOR); + +MODULE_LICENSE("GPL"); diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c index c7d90f17886..b90555cb808 100644 --- a/arch/xtensa/platforms/xt2000/setup.c +++ b/arch/xtensa/platforms/xt2000/setup.c @@ -69,7 +69,9 @@ void platform_restart(void) "wsr a2, icountlevel\n\t" "movi a2, 0\n\t" "wsr a2, icount\n\t" +#if XCHAL_NUM_IBREAK > 0 "wsr a2, ibreakenable\n\t" +#endif "wsr a2, lcount\n\t" "movi a2, 0x1f\n\t" "wsr a2, ps\n\t" @@ -90,18 +92,8 @@ void __init platform_setup(char** cmdline) /* early initialization */ -extern sysmem_info_t __initdata sysmem; - -void platform_init(bp_tag_t* first) +void __init platform_init(bp_tag_t *first) { - /* Set default memory block if not provided by the bootloader. */ - - if (sysmem.nr_banks == 0) { - sysmem.nr_banks = 1; - sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START; - sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START - + PLATFORM_DEFAULT_MEM_SIZE; - } } /* Heartbeat. Let the LED blink. */ diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h index 4416773cbde..aeb316b7ff8 100644 --- a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h +++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h @@ -15,10 +15,6 @@ #ifndef __XTENSA_XTAVNET_HARDWARE_H #define __XTENSA_XTAVNET_HARDWARE_H -/* By default NO_IRQ is defined to 0 in Linux, but we use the - interrupt 0 for UART... */ -#define NO_IRQ -1 - /* Memory configuration. */ #define PLATFORM_DEFAULT_MEM_START 0x00000000 @@ -30,7 +26,7 @@ /* Default assignment of LX60 devices to external interrupts. */ -#ifdef CONFIG_ARCH_HAS_SMP +#ifdef CONFIG_XTENSA_MX #define DUART16552_INTNUM XCHAL_EXTINT3_NUM #define OETH_IRQ XCHAL_EXTINT4_NUM #else diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index 4b9951a4569..57fd08b36f5 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -60,7 +60,9 @@ void platform_restart(void) "wsr a2, icountlevel\n\t" "movi a2, 0\n\t" "wsr a2, icount\n\t" +#if XCHAL_NUM_IBREAK > 0 "wsr a2, ibreakenable\n\t" +#endif "wsr a2, lcount\n\t" "movi a2, 0x1f\n\t" "wsr a2, ps\n\t" @@ -100,7 +102,7 @@ static void __init update_clock_frequency(struct device_node *node) } *(u32 *)newfreq->value = cpu_to_be32(*(u32 *)XTFPGA_CLKFRQ_VADDR); - prom_update_property(node, newfreq); + of_update_property(node, newfreq); } #define MAC_LEN 6 @@ -128,16 +130,16 @@ static void __init update_local_mac(struct device_node *node) memcpy(newmac->value, macaddr, MAC_LEN); ((u8*)newmac->value)[5] = (*(u32*)DIP_SWITCHES_VADDR) & 0x3f; - prom_update_property(node, newmac); + of_update_property(node, newmac); } static int __init machine_setup(void) { - struct device_node *serial; + struct device_node *clock; struct device_node *eth = NULL; - for_each_compatible_node(serial, NULL, "ns16550a") - update_clock_frequency(serial); + for_each_node_by_name(clock, "main-oscillator") + update_clock_frequency(clock); if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc"))) update_local_mac(eth); @@ -161,12 +163,12 @@ void platform_heartbeat(void) #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT -void platform_calibrate_ccount(void) +void __init platform_calibrate_ccount(void) { long clk_freq = 0; #ifdef CONFIG_OF struct device_node *cpu = - of_find_compatible_node(NULL, NULL, "xtensa,cpu"); + of_find_compatible_node(NULL, NULL, "cdns,xtensa-cpu"); if (cpu) { u32 freq; update_clock_frequency(cpu); @@ -177,8 +179,7 @@ void platform_calibrate_ccount(void) if (!clk_freq) clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR; - ccount_per_jiffy = clk_freq / HZ; - nsec_per_ccount = 1000000000UL / clk_freq; + ccount_freq = clk_freq; } #endif @@ -193,7 +194,7 @@ void platform_calibrate_ccount(void) * Ethernet -- OpenCores Ethernet MAC (ethoc driver) */ -static struct resource ethoc_res[] __initdata = { +static struct resource ethoc_res[] = { [0] = { /* register space */ .start = OETH_REGS_PADDR, .end = OETH_REGS_PADDR + OETH_REGS_SIZE - 1, @@ -211,7 +212,7 @@ static struct resource ethoc_res[] __initdata = { }, }; -static struct ethoc_platform_data ethoc_pdata __initdata = { +static struct ethoc_platform_data ethoc_pdata = { /* * The MAC address for these boards is 00:50:c2:13:6f:xx. * The last byte (here as zero) is read from the DIP switches on the @@ -221,7 +222,7 @@ static struct ethoc_platform_data ethoc_pdata __initdata = { .phy_id = -1, }; -static struct platform_device ethoc_device __initdata = { +static struct platform_device ethoc_device = { .name = "ethoc", .id = -1, .num_resources = ARRAY_SIZE(ethoc_res), @@ -235,13 +236,13 @@ static struct platform_device ethoc_device __initdata = { * UART */ -static struct resource serial_resource __initdata = { +static struct resource serial_resource = { .start = DUART16552_PADDR, .end = DUART16552_PADDR + 0x1f, .flags = IORESOURCE_MEM, }; -static struct plat_serial8250_port serial_platform_data[] __initdata = { +static struct plat_serial8250_port serial_platform_data[] = { [0] = { .mapbase = DUART16552_PADDR, .irq = DUART16552_INTNUM, @@ -254,7 +255,7 @@ static struct plat_serial8250_port serial_platform_data[] __initdata = { { }, }; -static struct platform_device xtavnet_uart __initdata = { +static struct platform_device xtavnet_uart = { .name = "serial8250", .id = PLAT8250_DEV_PLATFORM, .dev = { @@ -289,6 +290,7 @@ static int __init xtavnet_init(void) * knows whether they set it correctly on the DIP switches. */ pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr); + ethoc_pdata.eth_clkfreq = *(long *)XTFPGA_CLKFRQ_VADDR; return 0; } |
