summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/Kconfig28
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/bfin-otp.c189
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/serial/bfin_5xx.c56
5 files changed, 256 insertions, 20 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index a87b89db08e9..2906ee7bd298 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -481,6 +481,34 @@ config BRIQ_PANEL
It's safe to say N here.
+config BFIN_OTP
+ tristate "Blackfin On-Chip OTP Memory Support"
+ depends on BLACKFIN && (BF52x || BF54x)
+ default y
+ help
+ If you say Y here, you will get support for a character device
+ interface into the One Time Programmable memory pages that are
+ stored on the Blackfin processor. This will not get you access
+ to the secure memory pages however. You will need to write your
+ own secure code and reader for that.
+
+ To compile this driver as a module, choose M here: the module
+ will be called bfin-otp.
+
+ If unsure, it is safe to say Y.
+
+config BFIN_OTP_WRITE_ENABLE
+ bool "Enable writing support of OTP pages"
+ depends on BFIN_OTP
+ default n
+ help
+ If you say Y here, you will enable support for writing of the
+ OTP pages. This is dangerous by nature as you can only program
+ the pages once, so only enable this option when you actually
+ need it so as to not inadvertently clobber data.
+
+ If unsure, say N.
+
config PRINTER
tristate "Parallel printer support"
depends on PARPORT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 5407b7615614..4c1c584e9eb6 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_VIOTAPE) += viotape.o
obj-$(CONFIG_HVCS) += hvcs.o
obj-$(CONFIG_SGI_MBCS) += mbcs.o
obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o
+obj-$(CONFIG_BFIN_OTP) += bfin-otp.o
obj-$(CONFIG_PRINTER) += lp.o
obj-$(CONFIG_TIPAR) += tipar.o
diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
new file mode 100644
index 000000000000..0a01329451e4
--- /dev/null
+++ b/drivers/char/bfin-otp.c
@@ -0,0 +1,189 @@
+/*
+ * Blackfin On-Chip OTP Memory Interface
+ * Supports BF52x/BF54x
+ *
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#include <asm/blackfin.h>
+#include <asm/uaccess.h>
+
+#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
+#define stampit() stamp("here i am")
+#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
+
+#define DRIVER_NAME "bfin-otp"
+#define PFX DRIVER_NAME ": "
+
+static DEFINE_MUTEX(bfin_otp_lock);
+
+/* OTP Boot ROM functions */
+#define _BOOTROM_OTP_COMMAND 0xEF000018
+#define _BOOTROM_OTP_READ 0xEF00001A
+#define _BOOTROM_OTP_WRITE 0xEF00001C
+
+static u32 (* const otp_command)(u32 command, u32 value) = (void *)_BOOTROM_OTP_COMMAND;
+static u32 (* const otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_READ;
+static u32 (* const otp_write)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_WRITE;
+
+/* otp_command(): defines for "command" */
+#define OTP_INIT 0x00000001
+#define OTP_CLOSE 0x00000002
+
+/* otp_{read,write}(): defines for "flags" */
+#define OTP_LOWER_HALF 0x00000000 /* select upper/lower 64-bit half (bit 0) */
+#define OTP_UPPER_HALF 0x00000001
+#define OTP_NO_ECC 0x00000010 /* do not use ECC */
+#define OTP_LOCK 0x00000020 /* sets page protection bit for page */
+#define OTP_ACCESS_READ 0x00001000
+#define OTP_ACCESS_READWRITE 0x00002000
+
+/* Return values for all functions */
+#define OTP_SUCCESS 0x00000000
+#define OTP_MASTER_ERROR 0x001
+#define OTP_WRITE_ERROR 0x003
+#define OTP_READ_ERROR 0x005
+#define OTP_ACC_VIO_ERROR 0x009
+#define OTP_DATA_MULT_ERROR 0x011
+#define OTP_ECC_MULT_ERROR 0x021
+#define OTP_PREV_WR_ERROR 0x041
+#define OTP_DATA_SB_WARN 0x100
+#define OTP_ECC_SB_WARN 0x200
+
+/**
+ * bfin_otp_read - Read OTP pages
+ *
+ * All reads must be in half page chunks (half page == 64 bits).
+ */
+static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos)
+{
+ ssize_t bytes_done;
+ u32 page, flags, ret;
+ u64 content;
+
+ stampit();
+
+ if (count % sizeof(u64))
+ return -EMSGSIZE;
+
+ if (mutex_lock_interruptible(&bfin_otp_lock))
+ return -ERESTARTSYS;
+
+ bytes_done = 0;
+ page = *pos / (sizeof(u64) * 2);
+ while (bytes_done < count) {
+ flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
+ stamp("processing page %i (%s)", page, (flags == OTP_UPPER_HALF ? "upper" : "lower"));
+ ret = otp_read(page, flags, &content);
+ if (ret & OTP_MASTER_ERROR) {
+ bytes_done = -EIO;
+ break;
+ }
+ if (copy_to_user(buff + bytes_done, &content, sizeof(content))) {
+ bytes_done = -EFAULT;
+ break;
+ }
+ if (flags == OTP_UPPER_HALF)
+ ++page;
+ bytes_done += sizeof(content);
+ *pos += sizeof(content);
+ }
+
+ mutex_unlock(&bfin_otp_lock);
+
+ return bytes_done;
+}
+
+#ifdef CONFIG_BFIN_OTP_WRITE_ENABLE
+/**
+ * bfin_otp_write - Write OTP pages
+ *
+ * All writes must be in half page chunks (half page == 64 bits).
+ */
+static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos)
+{
+ stampit();
+
+ if (count % sizeof(u64))
+ return -EMSGSIZE;
+
+ if (mutex_lock_interruptible(&bfin_otp_lock))
+ return -ERESTARTSYS;
+
+ /* need otp_init() documentation before this can be implemented */
+
+ mutex_unlock(&bfin_otp_lock);
+
+ return -EINVAL;
+}
+#else
+# define bfin_otp_write NULL
+#endif
+
+static struct file_operations bfin_otp_fops = {
+ .owner = THIS_MODULE,
+ .read = bfin_otp_read,
+ .write = bfin_otp_write,
+};
+
+static struct miscdevice bfin_otp_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DRIVER_NAME,
+ .fops = &bfin_otp_fops,
+};
+
+/**
+ * bfin_otp_init - Initialize module
+ *
+ * Registers the device and notifier handler. Actual device
+ * initialization is handled by bfin_otp_open().
+ */
+static int __init bfin_otp_init(void)
+{
+ int ret;
+
+ stampit();
+
+ ret = misc_register(&bfin_otp_misc_device);
+ if (ret) {
+ pr_init(KERN_ERR PFX "unable to register a misc device\n");
+ return ret;
+ }
+
+ pr_init(KERN_INFO PFX "initialized\n");
+
+ return 0;
+}
+
+/**
+ * bfin_otp_exit - Deinitialize module
+ *
+ * Unregisters the device and notifier handler. Actual device
+ * deinitialization is handled by bfin_otp_close().
+ */
+static void __exit bfin_otp_exit(void)
+{
+ stampit();
+
+ misc_deregister(&bfin_otp_misc_device);
+}
+
+module_init(bfin_otp_init);
+module_exit(bfin_otp_exit);
+
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
+MODULE_DESCRIPTION("Blackfin OTP Memory Interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2399a3796f6e..015e16325973 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -827,7 +827,7 @@ config ULTRA32
config BFIN_MAC
tristate "Blackfin 527/536/537 on-chip mac support"
- depends on NET_ETHERNET && (BF527 || BF537 || BF536) && (!BF537_PORT_H)
+ depends on NET_ETHERNET && (BF527 || BF537 || BF536)
select CRC32
select MII
select PHYLIB
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 46bb47f37b9a..5f55534a290b 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -151,7 +151,8 @@ void kgdb_put_debug_char(int chr)
{
struct bfin_serial_port *uart;
- if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+ if (CONFIG_KGDB_UART_PORT < 0
+ || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
uart = &bfin_serial_ports[0];
else
uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
@@ -173,7 +174,8 @@ int kgdb_get_debug_char(void)
struct bfin_serial_port *uart;
unsigned char chr;
- if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+ if (CONFIG_KGDB_UART_PORT < 0
+ || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
uart = &bfin_serial_ports[0];
else
uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
@@ -192,7 +194,7 @@ int kgdb_get_debug_char(void)
}
#endif
-#if ANOMALY_05000230 && defined(CONFIG_SERIAL_BFIN_PIO)
+#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
# define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
#else
@@ -237,7 +239,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
}
#endif
- if (ANOMALY_05000230) {
+ if (ANOMALY_05000363) {
/* The BF533 (and BF561) family of processors have a nice anomaly
* where they continuously generate characters for a "single" break.
* We have to basically ignore this flood until the "next" valid
@@ -249,9 +251,6 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
* timeout was picked as it must absolutely be larger than 1
* character time +/- some percent. So 1.5 sounds good. All other
* Blackfin families operate properly. Woo.
- * Note: While Anomaly 05000230 does not directly address this,
- * the changes that went in for it also fixed this issue.
- * That anomaly was fixed in 0.5+ silicon. I like bunnies.
*/
if (anomaly_start.tv_sec) {
struct timeval curr;
@@ -285,7 +284,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
}
if (status & BI) {
- if (ANOMALY_05000230)
+ if (ANOMALY_05000363)
if (bfin_revid() < 5)
do_gettimeofday(&anomaly_start);
uart->port.icount.brk++;
@@ -507,8 +506,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
}
- uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
- add_timer(&(uart->rx_dma_timer));
+ mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
}
static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
@@ -551,9 +549,7 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
clear_dma_irqstat(uart->rx_dma_channel);
spin_unlock(&uart->port.lock);
- del_timer(&(uart->rx_dma_timer));
- uart->rx_dma_timer.expires = jiffies;
- add_timer(&(uart->rx_dma_timer));
+ mod_timer(&(uart->rx_dma_timer), jiffies);
return IRQ_HANDLED;
}
@@ -749,7 +745,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
unsigned long flags;
unsigned int baud, quot;
- unsigned short val, ier, lsr, lcr = 0;
+ unsigned short val, ier, lcr = 0;
switch (termios->c_cflag & CSIZE) {
case CS8:
@@ -806,10 +802,6 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
- do {
- lsr = UART_GET_LSR(uart);
- } while (!(lsr & TEMT));
-
/* Disable UART */
ier = UART_GET_IER(uart);
#ifdef CONFIG_BF54x
@@ -900,6 +892,31 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
return 0;
}
+/*
+ * Enable the IrDA function if tty->ldisc.num is N_IRDA.
+ * In other cases, disable IrDA function.
+ */
+static void bfin_set_ldisc(struct tty_struct *tty)
+{
+ int line = tty->index;
+ unsigned short val;
+
+ if (line >= tty->driver->num)
+ return;
+
+ switch (tty->ldisc.num) {
+ case N_IRDA:
+ val = UART_GET_GCTL(&bfin_serial_ports[line]);
+ val |= (IREN | RPOLC);
+ UART_PUT_GCTL(&bfin_serial_ports[line], val);
+ break;
+ default:
+ val = UART_GET_GCTL(&bfin_serial_ports[line]);
+ val &= ~(IREN | RPOLC);
+ UART_PUT_GCTL(&bfin_serial_ports[line], val);
+ }
+}
+
static struct uart_ops bfin_serial_pops = {
.tx_empty = bfin_serial_tx_empty,
.set_mctrl = bfin_serial_set_mctrl,
@@ -1172,7 +1189,7 @@ static struct uart_driver bfin_serial_reg = {
.dev_name = BFIN_SERIAL_NAME,
.major = BFIN_SERIAL_MAJOR,
.minor = BFIN_SERIAL_MINOR,
- .nr = NR_PORTS,
+ .nr = BFIN_UART_NR_PORTS,
.cons = BFIN_SERIAL_CONSOLE,
};
@@ -1261,6 +1278,7 @@ static int __init bfin_serial_init(void)
ret = uart_register_driver(&bfin_serial_reg);
if (ret == 0) {
+ bfin_serial_reg.tty_driver->set_ldisc = bfin_set_ldisc;
ret = platform_driver_register(&bfin_serial_driver);
if (ret) {
pr_debug("uart register failed\n");