You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
(12) |
May
(82) |
Jun
(72) |
Jul
(39) |
Aug
(104) |
Sep
(61) |
Oct
(55) |
Nov
(101) |
Dec
(48) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(52) |
Feb
(67) |
Mar
(18) |
Apr
(16) |
May
(33) |
Jun
(12) |
Jul
(102) |
Aug
(168) |
Sep
(65) |
Oct
(60) |
Nov
(43) |
Dec
(121) |
2002 |
Jan
(69) |
Feb
(32) |
Mar
(90) |
Apr
(59) |
May
(45) |
Jun
(43) |
Jul
(33) |
Aug
(21) |
Sep
(11) |
Oct
(20) |
Nov
(26) |
Dec
(3) |
2003 |
Jan
(12) |
Feb
(18) |
Mar
(11) |
Apr
(11) |
May
(41) |
Jun
(76) |
Jul
(77) |
Aug
(15) |
Sep
(38) |
Oct
(56) |
Nov
(19) |
Dec
(39) |
2004 |
Jan
(17) |
Feb
(52) |
Mar
(36) |
Apr
(34) |
May
(48) |
Jun
(85) |
Jul
(38) |
Aug
(42) |
Sep
(41) |
Oct
(77) |
Nov
(27) |
Dec
(19) |
2005 |
Jan
(32) |
Feb
(35) |
Mar
(29) |
Apr
(8) |
May
(7) |
Jun
(31) |
Jul
(46) |
Aug
(93) |
Sep
(65) |
Oct
(85) |
Nov
(219) |
Dec
(47) |
2006 |
Jan
(170) |
Feb
(103) |
Mar
(49) |
Apr
(43) |
May
(45) |
Jun
(29) |
Jul
(77) |
Aug
(82) |
Sep
(43) |
Oct
(45) |
Nov
(26) |
Dec
(85) |
2007 |
Jan
(42) |
Feb
(48) |
Mar
(64) |
Apr
(31) |
May
(88) |
Jun
(53) |
Jul
(175) |
Aug
(212) |
Sep
(91) |
Oct
(103) |
Nov
(110) |
Dec
(5) |
2008 |
Jan
(20) |
Feb
(11) |
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(5) |
Sep
(3) |
Oct
(12) |
Nov
|
Dec
|
From: Magnus D. <mag...@gm...> - 2007-09-06 04:38:02
|
sh: intc - irl mode update for sh7780 and sh7785 This patch contains the following fixes and improvements: - Fix address typo for INTMSK2 / INTMSKCLR2 registers on sh7780. - Adds IRQ_MODE_IRLnnnn_MASK using intc controller for IRL masking. - Good old IRQ_MODE_IRLnnnn should not register any intc controller. - plat_irq_setup_pins() now selects IRL or IRQ mode. - the holding function is now disabled using ICR0. By default all external pin interrupts are disabled. Signed-off-by: Magnus Damm <da...@ig...> --- arch/sh/kernel/cpu/sh4a/setup-sh7780.c | 43 ++++++++++++++++++++++++++++-- arch/sh/kernel/cpu/sh4a/setup-sh7785.c | 45 +++++++++++++++++++++++++++++++- include/asm-sh/hw_irq.h | 1 3 files changed, 85 insertions(+), 4 deletions(-) --- 0001/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ work/arch/sh/kernel/cpu/sh4a/setup-sh7780.c 2007-09-05 12:43:57.000000000 +0900 @@ -10,6 +10,7 @@ #include <linux/platform_device.h> #include <linux/init.h> #include <linux/serial.h> +#include <linux/io.h> #include <asm/sci.h> static struct resource rtc_resources[] = { @@ -239,7 +240,7 @@ static struct intc_vect irl_vectors[] __ }; static struct intc_mask_reg irl3210_mask_registers[] __initdata = { - { 0xffd00080, 0xffd00084, 32, /* INTMSK2 / INTMSKCLR2 */ + { 0xffd40080, 0xffd40084, 32, /* INTMSK2 / INTMSKCLR2 */ { IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH, IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH, IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH, @@ -247,7 +248,7 @@ static struct intc_mask_reg irl3210_mask }; static struct intc_mask_reg irl7654_mask_registers[] __initdata = { - { 0xffd00080, 0xffd00084, 32, /* INTMSK2 / INTMSKCLR2 */ + { 0xffd40080, 0xffd40084, 32, /* INTMSK2 / INTMSKCLR2 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH, IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH, @@ -261,8 +262,28 @@ static DECLARE_INTC_DESC(intc_irl7654_de static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7780-irl3210", irl_vectors, NULL, NULL, irl3210_mask_registers, NULL, NULL); +#define INTC_ICR0 0xffd00000 +#define INTC_INTMSK0 0xffd00044 +#define INTC_INTMSK1 0xffd00048 +#define INTC_INTMSK2 0xffd40080 +#define INTC_INTMSKCLR1 0xffd00068 +#define INTC_INTMSKCLR2 0xffd40084 + void __init plat_irq_setup(void) { + /* disable IRQ7-0 */ + ctrl_outl(0xff000000, INTC_INTMSK0); + + /* disable IRL3-0 + IRL7-4 */ + ctrl_outl(0xc0000000, INTC_INTMSK1); + ctrl_outl(0xfffefffe, INTC_INTMSK2); + + /* select IRL mode for IRL3-0 + IRL7-4 */ + ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); + + /* disable holding function, ie enable "SH-4 Mode" */ + ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0); + register_intc_controller(&intc_desc); } @@ -270,12 +291,28 @@ void __init plat_irq_setup_pins(int mode { switch (mode) { case IRQ_MODE_IRQ: + /* select IRQ mode for IRL3-0 + IRL7-4 */ + ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0); register_intc_controller(&intc_irq_desc); break; case IRQ_MODE_IRL7654: - register_intc_controller(&intc_irl7654_desc); + /* enable IRL7-4 but don't provide any masking */ + ctrl_outl(0x40000000, INTC_INTMSKCLR1); + ctrl_outl(0x0000fffe, INTC_INTMSKCLR2); break; case IRQ_MODE_IRL3210: + /* enable IRL0-3 but don't provide any masking */ + ctrl_outl(0x80000000, INTC_INTMSKCLR1); + ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); + break; + case IRQ_MODE_IRL7654_MASK: + /* enable IRL7-4 and mask using cpu intc controller */ + ctrl_outl(0x40000000, INTC_INTMSKCLR1); + register_intc_controller(&intc_irl7654_desc); + break; + case IRQ_MODE_IRL3210_MASK: + /* enable IRL0-3 and mask using cpu intc controller */ + ctrl_outl(0x80000000, INTC_INTMSKCLR1); register_intc_controller(&intc_irl3210_desc); break; default: --- 0001/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ work/arch/sh/kernel/cpu/sh4a/setup-sh7785.c 2007-09-05 12:41:44.000000000 +0900 @@ -10,6 +10,7 @@ #include <linux/platform_device.h> #include <linux/init.h> #include <linux/serial.h> +#include <linux/io.h> #include <asm/sci.h> static struct plat_sci_port sci_platform_data[] = { @@ -282,24 +283,66 @@ static DECLARE_INTC_DESC(intc_desc_irl01 static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7785-irl4567", vectors_irl4567, NULL, NULL, mask_registers, NULL, NULL); +#define INTC_ICR0 0xffd00000 +#define INTC_INTMSK0 0xffd00044 +#define INTC_INTMSK1 0xffd00048 +#define INTC_INTMSK2 0xffd40080 +#define INTC_INTMSKCLR1 0xffd00068 +#define INTC_INTMSKCLR2 0xffd40084 + void __init plat_irq_setup(void) { + /* disable IRQ3-0 + IRQ7-4 */ + ctrl_outl(0xff000000, INTC_INTMSK0); + + /* disable IRL3-0 + IRL7-4 */ + ctrl_outl(0xc0000000, INTC_INTMSK1); + ctrl_outl(0xfffefffe, INTC_INTMSK2); + + /* select IRL mode for IRL3-0 + IRL7-4 */ + ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); + + /* disable holding function, ie enable "SH-4 Mode" */ + ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0); + register_intc_controller(&intc_desc); } void __init plat_irq_setup_pins(int mode) { + ctrl_outl(0xc0000000, INTC_INTMSKCLR1); + ctrl_outl(0xfffefffe, INTC_INTMSKCLR2); + return; + switch (mode) { case IRQ_MODE_IRQ7654: + /* select IRQ mode for IRL7-4 */ + ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0); register_intc_controller(&intc_desc_irq4567); break; case IRQ_MODE_IRQ3210: + /* select IRQ mode for IRL3-0 */ + ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0); register_intc_controller(&intc_desc_irq0123); break; case IRQ_MODE_IRL7654: - register_intc_controller(&intc_desc_irl4567); + /* enable IRL7-4 but don't provide any masking */ + ctrl_outl(0x40000000, INTC_INTMSKCLR1); + ctrl_outl(0x0000fffe, INTC_INTMSKCLR2); break; case IRQ_MODE_IRL3210: + /* enable IRL0-3 but don't provide any masking */ + ctrl_outl(0x80000000, INTC_INTMSKCLR1); + ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); + break; + case IRQ_MODE_IRL7654_MASK: + /* enable IRL7-4 and mask using cpu intc controller */ + ctrl_outl(0x40000000, INTC_INTMSKCLR1); + register_intc_controller(&intc_desc_irl4567); + break; + case IRQ_MODE_IRL3210_MASK: + /* enable IRL0-3 and mask using cpu intc controller */ + ctrl_outl(0x80000000, INTC_INTMSKCLR1); register_intc_controller(&intc_desc_irl0123); break; default: --- 0001/include/asm-sh/hw_irq.h +++ work/include/asm-sh/hw_irq.h 2007-09-04 17:04:28.000000000 +0900 @@ -95,6 +95,7 @@ int intc_set_priority(unsigned int irq, void __init plat_irq_setup(void); enum { IRQ_MODE_IRQ, IRQ_MODE_IRQ7654, IRQ_MODE_IRQ3210, + IRQ_MODE_IRL7654_MASK, IRQ_MODE_IRL3210_MASK, IRQ_MODE_IRL7654, IRQ_MODE_IRL3210 }; void __init plat_irq_setup_pins(int mode); |
From: Magnus D. <mag...@gm...> - 2007-09-06 02:56:24
|
Hi there, On 9/1/07, shinkoi2005 <shi...@gm...> wrote: > Hi all. > > I have a problem about rts7751r2d. First of all, which board version are you using? It looks like your patch is targeted for R2D-1. I think CF support is disabled for R2D-1 just because of the problem your patch is trying to solve. The code that your patch modifies is used by both R2D-PLUS and R2D-1. I suspect that your current patch breaks R2D-PLUS. Or at least degrades it to 8 bit read. If these board versions doesn't make any sense to you then please read the help text for the new R2D specific board code available in the git tree that now is targeted for 2.6.24: http://git.kernel.org/?p=linux/kernel/git/lethal/sh-2.6.git;a=summary A few random hints: Please wrap your changes with CONFIG_RTS7751R2D_1 and make sure that CONFIG_RTS7751R2D_PLUS still compiles. Also, please add a signed-off line and make sure your patch applies to the tree above, not 2.6.23-rc. But I think you are already working against the sh-2.6 tree, right? Besides that I'm not sure if your patch is 100% correct. I know Paul is busy this week but maybe he has some comments later on. Is the libata code working properly with 8 bit reads? Is this patch all it takes to get CF working on R2D-1? Thanks for your help. / magnus |
From: Mike F. <va...@ge...> - 2007-09-05 04:37:17
|
On Tuesday 04 September 2007, Adrian McMenamin wrote: > --- a/drivers/input/keyboard/Kconfig > +++ b/drivers/input/keyboard/Kconfig > + Say Y here if you have a DreamCast console running Linux and have funny caps in Dreamcast > --- /dev/null > +++ b/drivers/input/keyboard/maple_keyb.c > +static void dc_scan_kbd(struct dc_kbd *kbd) still some funny wrappings in this func ... > + printk > + ("Unknown key (scancode %#x) released.", > + kbd->old[i]); > ... > + printk > + ("Unknown key (scancode %#x) pressed.", > + kbd->new[i]); missing KERN log levels in those printk's > +static int dc_kbd_connect(struct maple_device *dev) > +{ > ... > + struct dc_kbd *kbd; > ... > + kbd =3D kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); i find this more readable/managable myself: kbd =3D kzalloc(*kbd, GFP_KERNEL); > + kbd->dev =3D input_allocate_device(); > ... > + retval =3D input_register_device(kbd->dev); > + if (unlikely(retval)) > + goto cleanup; > ... > + cleanup: > + kfree(kbd); > + return -EINVAL; i'm not familiar with the input layer, but do you need to deallocate that=20 input device if the register fails ? if so, i guess dc_kbd_disconnect()=20 would need tweaking too ... =2Dmike |
From: Adrian M. <lkm...@gm...> - 2007-09-04 23:34:38
|
This patch will add support for the Dreamcast keyboard when used alongside the maple bus patch (http://lkml.org/lkml/2007/9/4/165) and the pvr2 patch. Signed off by: Adrian McMenamin <ad...@mc...> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c97d5eb..1689f73 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -253,4 +253,14 @@ config KEYBOARD_GPIO To compile this driver as a module, choose M here: the module will be called gpio-keys. + +config KEYBOARD_MAPLE + tristate "Maple bus keyboard" + depends on SH_DREAMCAST && MAPLE + help + Say Y here if you have a DreamCast console running Linux and have + a keyboard attached to its Maple bus. + + To compile this driver as a module, choose M here: the + module will be called maple_keyb. endif diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 28d211b..3f775ed 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -21,4 +21,5 @@ obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o +obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c new file mode 100644 index 0000000..12e4692 --- /dev/null +++ b/drivers/input/keyboard/maple_keyb.c @@ -0,0 +1,222 @@ +/* + * SEGA Dreamcast keyboard driver + * Based on drivers/usb/usbkbd.c + * Copyright YAEGASHI Takeshi, 2001 + * Porting to 2.6 Copyright Adrian McMenamin, 2007 + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/timer.h> +#include <linux/maple.h> + +MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin"); +MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver"); +MODULE_LICENSE("GPL"); + +static unsigned char dc_kbd_keycode[256] = { + 0, 0, 0, 0, 30, 48, 46, 32, + 18, 33, 34, 35, 23, 36, 37, 38, + 50, 49, 24, 25, 16, 19, 31, 20, + 22, 47, 17, 45, 21, 44, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 28, + 1, 14, 15, 57, 12, 13, 26, + 27, 43, 43, 39, 40, 41, 51, + 52, 53, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 87, 88, 99, + 70, 119, 110, 102, 104, 111, + 107, 109, 106, 105, 108, 103, + 69, 98, 55, 74, 78, 96, 79, 80, + 81, 75, 76, 77, 71, 72, 73, 82, 83, + 86, 127, 116, 117, 183, 184, 185, + 186, 187, 188, 189, 190, + 191, 192, 193, 194, 134, 138, 130, 132, + 128, 129, 131, 137, 133, 135, 136, 113, + 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, + 92, 94, 95, 0, 0, 0, + 122, 123, 90, 91, 85, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 42, 56, 125, 97, 54, 100, 126, + 164, 166, 165, 163, 161, 115, 114, 113, + 150, 158, 159, 128, 136, 177, 178, 176, 142, + 152, 173, 140 +}; + +struct dc_kbd { + struct input_dev *dev; + unsigned char new[8]; + unsigned char old[8]; +}; + +static void dc_scan_kbd(struct dc_kbd *kbd) +{ + int i; + struct input_dev *dev = kbd->dev; + for (i = 0; i < 8; i++) + input_report_key(dev, + dc_kbd_keycode[i + 224], + (kbd->new[0] >> i) & 1); + + for (i = 2; i < 8; i++) { + if (kbd->old[i] > 3 + && memchr(kbd->new + 2, kbd->old[i], 6) == NULL) { + if (dc_kbd_keycode[kbd->old[i]]) + input_report_key(dev, + dc_kbd_keycode[kbd->old[i]], 0); + else + printk + ("Unknown key (scancode %#x) released.", + kbd->old[i]); + } + + if (kbd->new[i] > 3 + && memchr(kbd->old + 2, kbd->new[i], 6) != NULL) { + if (dc_kbd_keycode[kbd->new[i]]) + input_report_key(dev, + dc_kbd_keycode[kbd->new[i]], 1); + else + printk + ("Unknown key (scancode %#x) pressed.", + kbd->new[i]); + } + } + input_sync(dev); + memcpy(kbd->old, kbd->new, 8); +} + +static void dc_kbd_callback(struct mapleq *mq) +{ + struct maple_device *mapledev = mq->dev; + struct dc_kbd *kbd = mapledev->private_data; + unsigned long *buf = mq->recvbuf; + if (buf[1] == mapledev->function) { + memcpy(kbd->new, buf + 2, 8); + dc_scan_kbd(kbd); + } +} + +static int dc_kbd_connect(struct maple_device *dev) +{ + int i, retval; + unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); + struct dc_kbd *kbd; + if (dev->function != MAPLE_FUNC_KEYBOARD) + return -EINVAL; + + kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); + if (unlikely(!kbd)) + return -ENOMEM; + + dev->private_data = kbd; + kbd->dev = input_allocate_device(); + if (unlikely(!kbd->dev)) + goto cleanup; + + kbd->dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + + for (i = 0; i < 255; i++) + set_bit(dc_kbd_keycode[i], kbd->dev->keybit); + + clear_bit(0, kbd->dev->keybit); + + kbd->dev->private = kbd; + + kbd->dev->name = dev->product_name; + kbd->dev->id.bustype = BUS_MAPLE; + + retval = input_register_device(kbd->dev); + if (unlikely(retval)) + goto cleanup; + + maple_getcond_callback(dev, dc_kbd_callback, (25 * HZ) / 1000, + MAPLE_FUNC_KEYBOARD); + + printk(KERN_INFO "input: keyboard(0x%lx): %s\n", data, + kbd->dev->name); + + return 0; + + cleanup: + kfree(kbd); + return -EINVAL; +} + +static void dc_kbd_disconnect(struct maple_device *dev) +{ + struct dc_kbd *kbd = dev->private_data; + + input_unregister_device(kbd->dev); + kfree(kbd); +} + +/* allow the keyboard to be used */ +static int probe_maple_kbd(struct device *dev) +{ + struct maple_device *mdev; + struct maple_driver *mdrv; + int proberes; + + mdev = to_maple_dev(dev); + mdrv = to_maple_driver(dev->driver); + + proberes = dc_kbd_connect(mdev); + if (unlikely(proberes)) + return proberes; + mdev->driver = mdrv; + mdev->registered = 1; + return 0; +} + + +static struct maple_driver dc_kbd_driver = { + .function = MAPLE_FUNC_KEYBOARD, + .connect = dc_kbd_connect, + .disconnect = dc_kbd_disconnect, + .drv = { + .name = "Dreamcast_keyboard", + .probe = probe_maple_kbd, + }, +}; + +static int __init dc_kbd_init(void) +{ + int retval; + retval = maple_driver_register(&dc_kbd_driver.drv); + if (retval) + return retval; + return 0; +} + +static void __exit dc_kbd_exit(void) +{ + driver_unregister(&dc_kbd_driver.drv); +} + +module_init(dc_kbd_init); +module_exit(dc_kbd_exit); diff --git a/include/linux/input.h b/include/linux/input.h index e02c6a6..2e65c88 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -688,6 +688,7 @@ struct input_absinfo { #define BUS_HOST 0x19 #define BUS_GSC 0x1A #define BUS_ATARI 0x1B +#define BUS_MAPLE 0x1C /* * Values describing the status of a force-feedback effect |
From: Adrian M. <lkm...@gm...> - 2007-09-04 23:27:24
|
The maple bus driver (http://lkml.org/lkml/2007/9/4/165) uses hardware synchronisation between the maple bus and the VBLANK to poll the maple bus. This patch makes the interrupt shareable. By definition the interrupt is for both devices. Signed-off by: Adrian McMenamin <ad...@mc...> diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 7d6c298..13de07f 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -890,7 +890,7 @@ static int __init pvr2fb_dc_init(void) pvr2_fix.mmio_start = 0xa05f8000; /* registers start here */ pvr2_fix.mmio_len = 0x2000; - if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, 0, + if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, IRQF_SHARED, "pvr2 VBL handler", fb_info)) { return -EBUSY; } |
From: Adrian M. <lkm...@gm...> - 2007-09-04 23:22:14
|
This patch adds support for SEGA's proprietary Maple bus. Maple is a serial communications bus and support is required to operate Dreamcast peripherals. A keyboard driver is also available and will be posted separately. Signed-off by: Adrian McMenamin <ad...@mc...> diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 54878f0..077438f 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -702,6 +702,17 @@ config CF_BASE_ADDR default "0xb8000000" if CF_AREA6 default "0xb4000000" if CF_AREA5 +config MAPLE + bool "Maple Bus Support" + depends on SH_DREAMCAST + help + The Maple Bus is SEGA's serial communication bus for peripherals + on the Dreamcast. Without this bus support you won't be able to + get your Dreamcast keyboard etc to work, so most users + probably want to say 'Y' here, unless you are only using the + Dreamcast with a serial line terminal or a remote network + connection. + source "arch/sh/drivers/pci/Kconfig" source "drivers/pci/Kconfig" diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 8a14389..f0a1f4f 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -3,4 +3,5 @@ # obj-$(CONFIG_SUPERHYWAY) += superhyway/ +obj-$(CONFIG_MAPLE) += maple/ diff --git a/drivers/sh/maple/Makefile b/drivers/sh/maple/Makefile new file mode 100644 index 0000000..f8c39f2 --- /dev/null +++ b/drivers/sh/maple/Makefile @@ -0,0 +1,3 @@ +#Makefile for Maple Bus + +obj-y := maplebus.o diff --git a/drivers/sh/maple/maplebus.c b/drivers/sh/maple/maplebus.c new file mode 100644 index 0000000..e6fd696 --- /dev/null +++ b/drivers/sh/maple/maplebus.c @@ -0,0 +1,738 @@ +/* maplebus.c + * Core maple bus functionality + * Original 2.4 code used here copyright + * YAEGASHI Takeshi, Paul Mundt, M. R. Brown and others + * Porting to 2.6 Copyright Adrian McMenamin, 2007 + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/init.h> +#include <linux/device.h> +#include <linux/moduleparam.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/maple.h> +#include <asm/cacheflush.h> +#include <asm/dma.h> +#include <asm/mach/sysasic.h> + +MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, MR Brown, Adrian McMenamin"); +MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}"); + +static void maple_dma_handler(struct work_struct *work); +static void maple_vblank_handler(struct work_struct *work); + +static DECLARE_WORK(maple_dma_process, maple_dma_handler); +static DECLARE_WORK(maple_vblank_process, maple_vblank_handler); + +static LIST_HEAD(maple_waitq); +static LIST_HEAD(maple_sentq); + + +static struct maple_driver maple_null_driver; +static struct device maple_bus; +static int subdevice_map[MAPLE_PORTS]; +static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; +static unsigned long maple_pnp_time; +static int started, scanning, liststatus; +static struct kmem_cache *maple_cache; + +int maple_driver_register(struct device_driver *drv) +{ + if (unlikely(!drv)) + return -EINVAL; + drv->bus = &maple_bus_type; + return driver_register(drv); +} +EXPORT_SYMBOL_GPL(maple_driver_register); + +void maplebus_init_hardware(void) +{ + ctrl_outl(MAPLE_MAGIC, MAPLE_RESET); + /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */ + ctrl_outl(1, MAPLE_TRIGTYPE); + ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED); + ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR); + ctrl_outl(1, MAPLE_ENABLE); +} +EXPORT_SYMBOL_GPL(maplebus_init_hardware); + +void maple_getcond_callback(struct maple_device *dev, + void (*callback) (struct mapleq * mq), + unsigned long interval, unsigned long function) +{ + dev->callback = callback; + dev->interval = interval; + dev->function = cpu_to_be32(function); + dev->when = 0; +} +EXPORT_SYMBOL_GPL(maple_getcond_callback); + +int maple_dma_done(void) +{ + return (ctrl_inl(MAPLE_STATE) & 1) == 0; +} +EXPORT_SYMBOL_GPL(maple_dma_done); + +static void maple_release_device(struct device *dev) +{ + if (likely(dev->type)) { + if (likely(dev->type->name)) + kfree(dev->type->name); + kfree(dev->type); + } +} + +void maple_add_packet(struct mapleq *mq) +{ + list_add((struct list_head *) mq, &maple_waitq); +} + +static struct mapleq *maple_allocq(struct maple_device *dev) +{ + struct mapleq *mq; + + mq = kmalloc(sizeof(*mq), GFP_KERNEL); + if (unlikely(!mq)) + return NULL; + + mq->dev = dev; + mq->recvbuf = kmem_cache_zalloc(maple_cache, GFP_KERNEL); + if (unlikely(!mq->recvbuf)) { + kfree(mq); + return NULL; + } + + return mq; +} + +static struct maple_device *maple_alloc_dev(int port, int unit) +{ + struct maple_device *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (unlikely(!dev)) + return NULL; + + dev->port = port; + dev->unit = unit; + dev->mq = maple_allocq(dev); + + if (unlikely(!dev->mq)) { + kfree(dev); + return NULL; + } + + return dev; +} + +static void maple_free_dev(struct maple_device *mdev) +{ + if (!mdev) + return; + kmem_cache_free(maple_cache, mdev->mq->recvbuf); + kfree(mdev->mq); + kfree(mdev); +} + +static void maple_build_block(struct mapleq *mq) +{ + int port, unit, from, to, len; + unsigned long *lsendbuf = mq->sendbuf; + + port = mq->dev->port & 3; + unit = mq->dev->unit; + len = mq->length; + from = port << 6; + to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20); + + *maple_lastptr &= 0x7fffffff; + maple_lastptr = maple_sendptr; + + *maple_sendptr++ = (port << 16) | len | 0x80000000; + *maple_sendptr++ = PHYSADDR(mq->recvbuf); + *maple_sendptr++ = + mq->command | (to << 8) | (from << 16) | (len << 24); + + while (len-- > 0) + *maple_sendptr++ = *lsendbuf++; +} + +void maple_send(void) +{ + int i; + int maple_packets; + struct mapleq *mq, *nmq; + + if (!list_empty(&maple_sentq)) + return; + if (list_empty(&maple_waitq) || !maple_dma_done()) + return; + maple_packets = 0; + maple_sendptr = maple_lastptr = maple_sendbuf; + list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { + maple_build_block(mq); + list_move(&mq->list, &maple_sentq); + if (unlikely(maple_packets++ > MAPLE_MAXPACKETS)) + break; + } + if (maple_packets > 0) { + for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) + dma_cache_wback_inv(maple_sendbuf + i * PAGE_SIZE, + PAGE_SIZE); + } +} + +static int attach_matching_maple_driver(struct device_driver *driver, + void *devptr) +{ + struct maple_driver *maple_drv; + struct maple_device *mdev; + + mdev = devptr; + maple_drv = to_maple_driver(driver); + if (unlikely + (mdev->devinfo.function & be32_to_cpu(maple_drv->function))) { + if (likely(maple_drv->connect(mdev) == 0)) { + mdev->driver = maple_drv; + return 1; + } + } + return 0; +} + +static void maple_detach_driver(struct maple_device *mdev) +{ + if (!mdev) + return; + if (likely(mdev->driver)) { + if (likely(mdev->driver->disconnect)) + mdev->driver->disconnect(mdev); + } + mdev->driver = NULL; + if (likely(mdev->registered)) { + maple_release_device(&mdev->dev); + device_unregister(&mdev->dev); + } + mdev->registered = 0; + maple_free_dev(mdev); +} + +static void maple_attach_driver(struct maple_device *dev) +{ + char *p; + + char *recvbuf; + unsigned long function; + int matched, retval; + + recvbuf = dev->mq->recvbuf; + memcpy(&dev->devinfo, recvbuf + 4, sizeof(dev->devinfo)); + memcpy(dev->product_name, dev->devinfo.product_name, 30); + memcpy(dev->product_licence, dev->devinfo.product_licence, 60); + dev->product_name[29] = '\0'; + dev->product_licence[59] = '\0'; + + for (p = dev->product_name + 28; dev->product_name <= p; p--) + if (*p == ' ') + *p = '\0'; + else + break; + + for (p = dev->product_licence + 58; dev->product_licence <= p; p--) + if (*p == ' ') + *p = '\0'; + else + break; + + function = be32_to_cpu(dev->devinfo.function); + + if (unlikely(function == 0xFFFFFFFF)) { + /* Do this silently - as not a real device */ + function = 0; + dev->driver = &maple_null_driver; + sprintf(dev->dev.bus_id, "%d:0.port", dev->port); + } else { + printk(KERN_INFO + "Maple bus at (%d, %d): Connected function 0x%lX\n", + dev->port, dev->unit, function); + + matched = + bus_for_each_drv(&maple_bus_type, NULL, dev, + attach_matching_maple_driver); + + if (matched == 0) { + /* Driver does not exist yet */ + printk(KERN_INFO + "No maple driver found for this device\n"); + dev->driver = &maple_null_driver; + } + + sprintf(dev->dev.bus_id, "%d:0%d.%lX", dev->port, + dev->unit, function); + } + dev->function = function; + dev->dev.bus = &maple_bus_type; + dev->dev.parent = &maple_bus; + dev->dev.release = &maple_release_device; + retval = device_register(&dev->dev); + if (retval) { + printk(KERN_INFO + "Maple bus: Attempt to register device (%x, %x) failed.\n", + dev->port, dev->unit); + maple_free_dev(dev); + } + dev->registered = 1; +} + +/* if device has been registered for the given + * port and unit then return 1 - allows identification + * of which devices need to be attached or detached + */ +static int detach_maple_device(struct device *device, void *portptr) +{ + struct device_specify *ds; + struct maple_device *mdev; + + ds = portptr; + mdev = to_maple_dev(device); + if (unlikely(mdev->port == ds->port && mdev->unit == ds->unit)) + return 1; + return 0; +} + +static int setup_maple_commands(struct device *device, void *ignored) +{ + struct maple_device *maple_dev = to_maple_dev(device); + + if (likely(maple_dev->interval > 0)) { + if (likely(jiffies > maple_dev->when)) { + maple_dev->when = jiffies + maple_dev->interval; + maple_dev->mq->command = MAPLE_COMMAND_GETCOND; + maple_dev->mq->sendbuf = &maple_dev->function; + maple_dev->mq->length = 1; + maple_add_packet(maple_dev->mq); + liststatus++; + } + } else { + if (jiffies >= maple_pnp_time) { + maple_dev->mq->command = MAPLE_COMMAND_DEVINFO; + maple_dev->mq->length = 0; + maple_add_packet(maple_dev->mq); + liststatus++; + } + } + + return 0; +} + +static void maple_vblank_handler(struct work_struct *work) +{ + /* Turn off Maple DMA while we do this */ + if (unlikely(!maple_dma_done())) + return; + if (unlikely(!list_empty(&maple_sentq))) + return; + ctrl_outl(0, MAPLE_ENABLE); + liststatus = 0; + bus_for_each_dev(&maple_bus_type, NULL, NULL, + setup_maple_commands); + if (jiffies >= maple_pnp_time) + maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; + if (likely(liststatus && list_empty(&maple_sentq))) { + INIT_LIST_HEAD(&maple_sentq); + maple_send(); + } + maplebus_init_hardware(); +} + +static void maple_map_subunits(struct maple_device *mdev, int submask) +{ + int retval, k, devcheck; + struct maple_device *mdev_add; + struct device_specify ds; + + for (k = 0; k < 5; k++) { + ds.port = mdev->port; + ds.unit = k + 1; + retval = + bus_for_each_dev(&maple_bus_type, NULL, &ds, + detach_maple_device); + if (retval) { + submask = submask >> 1; + continue; + } + devcheck = submask & 0x01; + if (unlikely(devcheck)) { + mdev_add = maple_alloc_dev(mdev->port, k + 1); + mdev_add->mq->command = MAPLE_COMMAND_DEVINFO; + mdev_add->mq->length = 0; + maple_add_packet(mdev_add->mq); + scanning = 1; + } + submask = submask >> 1; + } +} + +static void maple_clean_submap(struct maple_device *mdev) +{ + int killbit; + + killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20); + killbit = ~killbit; + killbit &= 0xFF; + subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit; +} + +static void maple_response_none(struct maple_device *mdev, + struct mapleq *mq) +{ + if (unlikely(!started)) { + printk(KERN_INFO "No maple devices attached to port %d\n", + mdev->port); + maple_attach_driver(mdev); + return; + } + if (unlikely(mdev->unit != 0)) { + list_del(&mq->list); + maple_detach_driver(mdev); + maple_clean_submap(mdev); + printk(KERN_INFO "Maple bus detaching at (%d, %d)\n", + mdev->port, mdev->unit); + return; + } + maple_clean_submap(mdev); +} + +static void maple_response_devinfo(struct maple_device *mdev, + char *recvbuf) +{ + char submask; + if ((unlikely(!started)) || (unlikely(scanning == 2))) { + maple_attach_driver(mdev); + return; + } + if (likely(mdev->unit == 0)) { + submask = recvbuf[2] & 0x1F; + if (unlikely(submask ^ subdevice_map[mdev->port])) { + maple_map_subunits(mdev, submask); + subdevice_map[mdev->port] = submask; + } + } +} + +static void maple_dma_handler(struct work_struct *work) +{ + struct mapleq *mq, *nmq; + struct maple_device *dev; + char *recvbuf; + enum maple_code code; + + if (unlikely(!maple_dma_done())) + return; + ctrl_outl(0, MAPLE_ENABLE); + + /* Be extra cautious and check new DMA cycle not already underway */ + if (likely(!list_empty(&maple_sentq))) { + list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { + recvbuf = mq->recvbuf; + code = recvbuf[0]; + dev = mq->dev; + switch (code) { + case MAPLE_RESPONSE_NONE: + maple_response_none(dev, mq); + break; + + case MAPLE_RESPONSE_DEVINFO: + maple_response_devinfo(dev, recvbuf); + break; + + case MAPLE_RESPONSE_DATATRF: + if (dev->callback) + dev->callback(mq); + break; + + case MAPLE_RESPONSE_FILEERR: + case MAPLE_RESPONSE_AGAIN: + case MAPLE_RESPONSE_BADCMD: + case MAPLE_RESPONSE_BADFUNC: + printk(KERN_DEBUG + "Maple non-fatal error 0x%X\n", + code); + break; + + case MAPLE_RESPONSE_ALLINFO: + printk(KERN_DEBUG + "Maple - extended device information not supported\n"); + break; + + case MAPLE_RESPONSE_OK: + break; + + default: + break; + } + } + INIT_LIST_HEAD(&maple_sentq); + if (unlikely(scanning == 1)) { + maple_send(); + scanning = 2; + } else + scanning = 0; + + if (unlikely(started == 0)) + started = 1; + } + maplebus_init_hardware(); +} + +static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id) +{ + /* Load everything into the bottom half */ + schedule_work(&maple_dma_process); + return IRQ_HANDLED; +} + +static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id) +{ + schedule_work(&maple_vblank_process); + return IRQ_HANDLED; +} + +static struct irqaction maple_dma_irq = { + .name = "maple bus DMA handler", + .handler = maplebus_dma_interrupt, + .flags = IRQF_SHARED, +}; + +static struct irqaction maple_vblank_irq = { + .name = "maple bus VBLANK handler", + .handler = maplebus_vblank_interrupt, + .flags = IRQF_SHARED, +}; + +static int maple_set_dma_interrupt_handler(void) +{ + return setup_irq(HW_EVENT_MAPLE_DMA, &maple_dma_irq); +} + +static int maple_set_vblank_interrupt_handler(void) +{ + return setup_irq(HW_EVENT_VSYNC, &maple_vblank_irq); +} + +static int maple_get_dma_buffer(void) +{ + maple_sendbuf = + (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, + MAPLE_DMA_PAGES); + if (unlikely(!maple_sendbuf)) + return -ENOMEM; + return 0; +} + +static int match_maple_bus_driver(struct device *devptr, + struct device_driver *drvptr) +{ + struct maple_driver *maple_drv; + struct maple_device *maple_dev; + + maple_drv = container_of(drvptr, struct maple_driver, drv); + maple_dev = container_of(devptr, struct maple_device, dev); + /* Trap empty port case */ + if (unlikely(maple_dev->devinfo.function == 0xFFFFFFFF)) + return 0; + else if (unlikely + (maple_dev->devinfo.function & + be32_to_cpu(maple_drv->function))) + return 1; + return 0; +} + +static int maple_bus_uevent(struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size) +{ + return 0; +} + +static void maple_bus_release(struct device *dev) +{ +} + +static struct maple_driver maple_null_driver = { + .drv = { + .name = "Maple_bus_basic_driver", + .bus = &maple_bus_type, + }, +}; + +struct bus_type maple_bus_type = { + .name = "maple", + .match = match_maple_bus_driver, + .uevent = maple_bus_uevent, +}; + +EXPORT_SYMBOL_GPL(maple_bus_type); + +static struct device maple_bus = { + .bus_id = "maple", + .release = maple_bus_release, +}; + +static int __init maple_bus_init(void) +{ + int retval, i; + struct maple_device *mdev[MAPLE_PORTS]; + ctrl_outl(0, MAPLE_STATE); + + retval = device_register(&maple_bus); + if (unlikely(retval)) + goto cleanup; + + retval = bus_register(&maple_bus_type); + if (unlikely(retval)) + goto cleanup_device; + + retval = driver_register(&maple_null_driver.drv); + + if (unlikely(retval)) + goto cleanup_bus; + + /* allocate memory for maple bus dma */ + retval = maple_get_dma_buffer(); + if (unlikely(retval)) { + printk(KERN_INFO + "Maple bus: Failed to allocate Maple DMA buffers\n"); + goto cleanup_basic; + } + + /* set up DMA interrupt handler */ + retval = maple_set_dma_interrupt_handler(); + if (unlikely(retval)) { + printk(KERN_INFO + "Maple bus: Failed to grab maple DMA IRQ\n"); + goto cleanup_dma; + } + + /* set up VBLANK interrupt handler */ + retval = maple_set_vblank_interrupt_handler(); + if (unlikely(retval)) { + printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n"); + goto cleanup_irq; + } + + maple_cache = + kmem_cache_create("Maplebus_cache", 0x400, 0, + SLAB_HWCACHE_ALIGN, NULL); + + if (unlikely(!maple_cache)) + goto cleanup_bothirqs; + + /* setup maple ports */ + for (i = 0; i < MAPLE_PORTS; i++) { + mdev[i] = maple_alloc_dev(i, 0); + if (unlikely(!mdev[i])) { + while (i-- > 0) + maple_free_dev(mdev[i]); + goto cleanup_cache; + } + mdev[i]->registered = 0; + mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO; + mdev[i]->mq->length = 0; + maple_add_packet(mdev[i]->mq); + subdevice_map[i] = 0; + } + + /* setup maplebus hardware */ + maplebus_init_hardware(); + + /* initial detection */ + maple_send(); + + maple_pnp_time = 0; + + printk(KERN_INFO "Maple bus core now registered.\n"); + + return 0; + + cleanup_cache: + kmem_cache_destroy(maple_cache); + + cleanup_bothirqs: + free_irq(HW_EVENT_VSYNC, 0); + + cleanup_irq: + free_irq(HW_EVENT_MAPLE_DMA, 0); + + cleanup_dma: + free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); + + cleanup_basic: + driver_unregister(&maple_null_driver.drv); + + cleanup_bus: + bus_unregister(&maple_bus_type); + + cleanup_device: + device_unregister(&maple_bus); + + cleanup: + printk(KERN_INFO "Maple bus registration failed\n"); + return retval; +} + +static int maple_remove_driver(struct device_driver *driver, void *ignored) +{ + driver_unregister(driver); + return 0; +} + +static int maple_remove_device(struct device *dev, void *ignored) +{ + struct maple_device *mdev; + mdev = to_maple_dev(dev); + maple_detach_driver(mdev); + return 0; +} + +static void __exit maple_bus_exit(void) +{ + int ignored; + free_irq(HW_EVENT_MAPLE_DMA, 0); + free_irq(HW_EVENT_VSYNC, 0); + + ignored = bus_for_each_drv(&maple_bus_type, NULL, NULL, + maple_remove_driver); + ignored = bus_for_each_dev(&maple_bus_type, NULL, NULL, + maple_remove_device); + + bus_unregister(&maple_bus_type); + device_unregister(&maple_bus); + + kmem_cache_destroy(maple_cache); + + if (likely(maple_sendbuf)) + free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); +} + +/* use init call to ensure bus is registered ahead of devices */ +subsys_initcall(maple_bus_init); +module_exit(maple_bus_exit); diff --git a/include/linux/maple.h b/include/linux/maple.h new file mode 100644 index 0000000..f74a110 --- /dev/null +++ b/include/linux/maple.h @@ -0,0 +1,126 @@ +/** + * maple.h + * + * porting to 2.6 driver model + * copyright Adrian McMenamin, 2007 + * + */ + +extern struct bus_type maple_bus_type; +extern struct semaphore maple_mutex; + +#define MAPLE_PORTS 4 +#define MAPLE_PNP_INTERVAL HZ +#define MAPLE_MAXPACKETS 8 +#define MAPLE_DMA_ORDER 14 +#define MAPLE_DMA_SIZE (1 << MAPLE_DMA_ORDER) +#define MAPLE_DMA_PAGES ((MAPLE_DMA_ORDER > PAGE_SHIFT) ? MAPLE_DMA_ORDER - PAGE_SHIFT : 0) + +/* Maple Bus registers */ +#define MAPLE_BASE 0xa05f6c00 +#define MAPLE_DMAADDR (MAPLE_BASE+0x04) +#define MAPLE_TRIGTYPE (MAPLE_BASE+0x10) +#define MAPLE_ENABLE (MAPLE_BASE+0x14) +#define MAPLE_STATE (MAPLE_BASE+0x18) +#define MAPLE_SPEED (MAPLE_BASE+0x80) +#define MAPLE_RESET (MAPLE_BASE+0x8c) + +#define MAPLE_MAGIC 0x6155404f +#define MAPLE_2MBPS 0 +#define MAPLE_TIMEOUT(n) ((n)<<15) + +/* Maple Bus command and response codes */ +enum maple_code { + MAPLE_RESPONSE_FILEERR = -5, + MAPLE_RESPONSE_AGAIN = -4, /* request should be retransmitted */ + MAPLE_RESPONSE_BADCMD = -3, + MAPLE_RESPONSE_BADFUNC = -2, + MAPLE_RESPONSE_NONE = -1, /* unit didn't respond at all */ + MAPLE_COMMAND_DEVINFO = 1, + MAPLE_COMMAND_ALLINFO = 2, + MAPLE_COMMAND_RESET = 3, + MAPLE_COMMAND_KILL = 4, + MAPLE_RESPONSE_DEVINFO = 5, + MAPLE_RESPONSE_ALLINFO = 6, + MAPLE_RESPONSE_OK = 7, + MAPLE_RESPONSE_DATATRF = 8, + MAPLE_COMMAND_GETCOND = 9, + MAPLE_COMMAND_GETMINFO = 10, + MAPLE_COMMAND_BREAD = 11, + MAPLE_COMMAND_BWRITE = 12, + MAPLE_COMMAND_SETCOND = 14 +}; + +/* Function codes */ + +#define MAPLE_FUNC_CONTROLLER 0x001 +#define MAPLE_FUNC_MEMCARD 0x002 +#define MAPLE_FUNC_LCD 0x004 +#define MAPLE_FUNC_CLOCK 0x008 +#define MAPLE_FUNC_MICROPHONE 0x010 +#define MAPLE_FUNC_ARGUN 0x020 +#define MAPLE_FUNC_KEYBOARD 0x040 +#define MAPLE_FUNC_LIGHTGUN 0x080 +#define MAPLE_FUNC_PURUPURU 0x100 +#define MAPLE_FUNC_MOUSE 0x200 + +struct mapleq { + struct list_head list; + struct maple_device *dev; + void *sendbuf, *recvbuf; + unsigned char length; + enum maple_code command; +}; + +struct maple_devinfo { + unsigned long function; + unsigned long function_data[3]; + unsigned char area_code; + unsigned char connector_directon; + char product_name[30]; + char product_licence[60]; + unsigned short standby_power; + unsigned short max_power; +}; + +struct maple_device { + struct maple_driver *driver; + struct mapleq *mq; + void *private_data; + void (*callback) (struct mapleq * mq); + unsigned long when, interval, function; + struct maple_devinfo devinfo; + unsigned char port, unit; + char product_name[32]; + char product_licence[64]; + int registered; + struct device dev; +}; + +struct maple_driver { + unsigned long function; + int (*connect) (struct maple_device * dev); + void (*disconnect) (struct maple_device * dev); + struct device_driver drv; +}; + +struct device_specify { + int port; + int unit; +}; + +void maple_getcond_callback(struct maple_device *dev, + void (*callback) (struct mapleq * mq), + unsigned long interval, + unsigned long function); + +void maple_setup_port_rescan(struct maple_device *mdev); + +void maplebus_init_hardware(void); + +int maple_dma_done(void); + +int maple_driver_register(struct device_driver *drv); + +#define to_maple_dev(n) container_of(n, struct maple_device, dev) +#define to_maple_driver(n) container_of(n, struct maple_driver, drv) |
From: Kristoffer E. <kri...@gm...> - 2007-09-04 21:18:54
|
Greetings, Trying to wrap my head around the pcmcia driver, Im getting this error when inserting card: unexpected IRQ trap at vector 4f irq 79, desc:8c2c5a1c, depth: 1 ->handle_irq(): 8c031080, handle_bad_irq+0x0/0x2d0 ->chip(): 8c2f1140, 0x8c2f1140 ->action(): 00000000 IRQ_DISABLED_SET As paul before pointed out this is probably due to bad IRQ handler. Thats what Im wondering about : IRQ 36 is used by HD64461, it registers a demux that handles 64->80, HD64461_SS is set at 78 and uses a demux to handle additional sockets (only one needed), that gets 79. It uses irq_desc[79].chip = &hd64461_ss_irq_type; to aquire the handler for that interrupt. Now here's my question. The interrupt 79 is initially set to use hd64461_demux handler but is later replaced by hd64461_ss handler. I assume this is possible without any issues, or should I lower the hd64461 to only control up to 78? I've set the mach_vector for hp6xx to use 64 + 16 + 6 IRQ's just to be on the safe side. And I also need one additional for the keyboard polling interrupt. Hope you understand my question, abit dizy atm :) Best wishes Kristoffer |
From: Adrian M. <ad...@ne...> - 2007-09-03 23:39:20
|
I am continuing to work on the maple bus driver for the Dreamcast - the issues are fundamentally about stability. The old driver took a 1024 byte statically allocated block and applied P2SEGADDR to it. I am now using the slab allocator and I was getting a lot of "unaligned fix up" errors, though when I removed that, and just used the allocated P1 address the code appears, empirically and on first blush, to be more stable. Is that likely? Any reason - bad toolchain? - or am I likely to just not to have tested the cases enough? |
From: shinkoi2005 <shi...@gm...> - 2007-09-01 11:41:19
|
Hi all. I have a problem about rts7751r2d. I think that rts7751r2d's cf_ide resister mapped area is Area5. And Area5's access size is 16bit width (see manual http://tree.celinuxforum.org/CelfPubWiki/RTS7751R2DHandlingManual?action=AttachFile&do=get&target=R2DHWmanual.pdf p.27). But libata-core.c uses ioread8()/iowrite8() that access size is 8bit width. So we need to change access size. ------ diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c index e62107d..d9fbdc2 100644 --- a/arch/sh/boards/renesas/rts7751r2d/setup.c +++ b/arch/sh/boards/renesas/rts7751r2d/setup.c @@ -45,12 +45,12 @@ static void __init voyagergx_serial_init(void) static struct resource cf_ide_resources[] = { [0] = { .start = PA_AREA5_IO + 0x1000, - .end = PA_AREA5_IO + 0x1000 + 0x08 - 1, + .end = PA_AREA5_IO + 0x1000 + 0x10 - 0x2, .flags = IORESOURCE_MEM, }, [1] = { .start = PA_AREA5_IO + 0x80c, - .end = PA_AREA5_IO + 0x80c + 0x16 - 1, + .end = PA_AREA5_IO + 0x80c, .flags = IORESOURCE_MEM, }, [2] = { @@ -141,19 +141,12 @@ static struct platform_device *rts7751r2d_devices[] __initdata = { &uart_device, &sm501_device, #endif + &cf_ide_device, &heartbeat_device, }; static int __init rts7751r2d_devices_setup(void) { - int ret; - - if (ctrl_inw(PA_BVERREG) == 0x10) { /* R2D-PLUS */ - ret = platform_device_register(&cf_ide_device); - if (ret) - return ret; - } - return platform_add_devices(rts7751r2d_devices, ARRAY_SIZE(rts7751r2d_devices)); } @@ -182,6 +175,36 @@ static void __init rts7751r2d_setup(char **cmdline_p) voyagergx_serial_init(); } +static inline unsigned char is_ide_ioaddr(unsigned long addr) { + if ((cf_ide_resources[0].start <= addr && + addr <= cf_ide_resources[0].end) || + (cf_ide_resources[1].start <= addr && + addr <= cf_ide_resources[1].end)) { + return 1; + } + return 0; +} + +void rts7751r2d_writeb(u8 b, void __iomem *addr) +{ + unsigned long tmp = (unsigned long __force)addr; + + if (is_ide_ioaddr(tmp)) + ctrl_outw((u16)b, tmp); + else + ctrl_outb(b, tmp); +} + +u8 rts7751r2d_readb(void __iomem *addr) +{ + unsigned long tmp = (unsigned long __force)addr; + + if (is_ide_ioaddr(tmp)) + return 0xff & ctrl_inw(tmp); + else + return ctrl_inb(tmp); +} + /* * The Machine Vector */ @@ -191,6 +214,8 @@ static struct sh_machine_vector mv_rts7751r2d __initmv = { .mv_init_irq = init_rts7751r2d_IRQ, .mv_irq_demux = rts7751r2d_irq_demux, + .mv_writeb = rts7751r2d_writeb, + .mv_readb = rts7751r2d_readb, #if defined(CONFIG_MFD_SM501) && defined(CONFIG_USB_OHCI_HCD) .mv_consistent_alloc = voyagergx_consistent_alloc, |
From: Adrian M. <ad...@ne...> - 2007-09-01 09:36:10
|
On Fri, 2007-08-31 at 23:02 -0400, Mike Frysinger wrote: > i really dont know how the maple bus works or what piece of hardware is wired > up to the same interrupt line. my point is that if the other device fires an > interrupt, the pvr interrupt handler may be executed and attempt to do work > when in reality the pvr was not the source of the interrupt. > -mike The interrupt is *always* fired by the PVR - it is the VBLANK - ie essentially screen refresh. It is *never* generated by the maple bus. However, the maple bus is/can be hardware synced - which means once that setting is made then the hardware will *always* be polled on the VBLANK. In other words there is no need to check which device is interrupt is for, because it is *always* going to be for both of them. |
From: Mike F. <va...@ge...> - 2007-09-01 03:02:37
|
On Friday 31 August 2007, Adrian McMenamin wrote: > On 31/08/2007, Mike Frysinger <vap...@gm...> wrote: > > On 8/31/07, Adrian McMenamin <lkm...@gm...> wrote: > > > This patch makes the PVR2 VBLANK interrupt on the SEGA Dreamcast > > > shareable - a small but necessary change to enable ongoing efforts to > > > develop a driver for the maple bus on the Dreamcast. (Maple is Sega's > > > proprietary serial interface for the Dreamcast and can be set to > > > synchronise dma transfers to the VBLANK). > > > > > > This has no impact on the performance of the PVR2. > > > > sharable implies the interrupt handler checks to see if it actually > > caused the interrupt ... which it doesnt at the moment ... presumably, > > you're making it shared because another device will be using that > > interrupt as well ... so when that other device gets an interrupt, how > > do you know it's for that device and not PVR2 ? > > If the interrupt occurs then it will be for both of them. The hardware > cannot be removed and the maple bus driver is set for hardware sync. > > The question seems redundant to me. i really dont know how the maple bus works or what piece of hardware is wir= ed=20 up to the same interrupt line. my point is that if the other device fires = an=20 interrupt, the pvr interrupt handler may be executed and attempt to do work= =20 when in reality the pvr was not the source of the interrupt. =2Dmike |
From: Adrian M. <lkm...@gm...> - 2007-08-31 20:14:38
|
On 31/08/2007, Mike Frysinger <vap...@gm...> wrote: > On 8/31/07, Adrian McMenamin <lkm...@gm...> wrote: > > This patch makes the PVR2 VBLANK interrupt on the SEGA Dreamcast > > shareable - a small but necessary change to enable ongoing efforts to > > develop a driver for the maple bus on the Dreamcast. (Maple is Sega's > > proprietary serial interface for the Dreamcast and can be set to > > synchronise dma transfers to the VBLANK). > > > > This has no impact on the performance of the PVR2. > > sharable implies the interrupt handler checks to see if it actually > caused the interrupt ... which it doesnt at the moment ... presumably, > you're making it shared because another device will be using that > interrupt as well ... so when that other device gets an interrupt, how > do you know it's for that device and not PVR2 ? If the interrupt occurs then it will be for both of them. The hardware cannot be removed and the maple bus driver is set for hardware sync. The question seems redundant to me. |
From: Adrian M. <lkm...@gm...> - 2007-08-31 20:06:14
|
Apologies, sent this Bcc by mistake the first time ---------- Forwarded message ---------- From: Adrian McMenamin <lkm...@gm...> Date: 31 Aug 2007 21:00 Subject: [PATCH] Patch pvr2 driver to allow development of maple bus driver To: "Antonino A. Daplas" <ad...@gm...> This patch makes the PVR2 VBLANK interrupt on the SEGA Dreamcast shareable - a small but necessary change to enable ongoing efforts to develop a driver for the maple bus on the Dreamcast. (Maple is Sega's proprietary serial interface for the Dreamcast and can be set to synchronise dma transfers to the VBLANK). This has no impact on the performance of the PVR2. Signed-off by Adrian McMenamin <ad...@mc...> diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 7d6c298..13de07f 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -890,7 +890,7 @@ static int __init pvr2fb_dc_init(void) pvr2_fix.mmio_start = 0xa05f8000; /* registers start here */ pvr2_fix.mmio_len = 0x2000; - if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, 0, + if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, IRQF_SHARED, "pvr2 VBL handler", fb_info)) { return -EBUSY; } |
From: Kristoffer E. <kri...@gm...> - 2007-08-31 14:03:16
|
Greetings, I placed it inside setup.c after all the usual inits but this only caused the jornada to freeze at bootup. Im guessing it needs to be done before. Any suggestion where? IRQ0->IRQ3 are needed for Touchscreen, APM among other things. -- Kristoffer Ericson <Kri...@Gm...> |
From: Kristoffer E. <kri...@gm...> - 2007-08-30 15:38:11
|
On Thu, 30 Aug 2007 09:02:20 +0900 Paul Mundt <le...@li...> wrote: > On Wed, Aug 29, 2007 at 06:06:00PM -0700, Kristoffer Ericson wrote: > > On Wed, 29 Aug 2007 18:09:47 +0900 > > Paul Mundt <le...@li...> wrote: > > > > > On Tue, Aug 28, 2007 at 08:03:50PM -0700, Kristoffer Ericson wrote: > > > > The hd64461 have two slots (CF/PCMCIA) but since CF is handled by > > > > libata (and initial start in hd64461.c) should this driver be able to > > > > handle both CF and PCMCIA? > > > > > > > > Personally i feel it would make more sense if it only controlled the > > > > pcmcia. Anyone wanting CF support could easily add that for their > > > > platform. > > > > > > > > Before we never used the CF slot but instead let ide-sh handle it. > > > > > > > I'm not sure I understand your question. HD64461 is a multi-function > > > device, meaning that you have a driver for each defined function. Usually > > > these need to chain in to the MFD driver for things like IRQ demux and > > > things like that, but each function is generally wholly isolated. > > I put my words poorly, what I ment was, is it resonable that the hd64461_SS driver should > > handle the CF slot aswell as the pcmcia one? > > Currently its set to only handle the pcmcia, but you can through menuconfig make it also > > control the CF slot. > > > For storage devices it doesn't really matter, but keep in mind that there > are also non-storage CF devices, so you may want to handle both cases. I > would focus on PCMCIA first and worry about the corner cases later, > however. Thats the thing, the CF slot can only handle memory/storage card (hardware limitation). So, if I drop support for the CF slot in hd64461_ss users shouldn't miss anything. Thats why Im so eager to get rid of it in hd64461_ss, since it feels like un-needed support. |
From: Paul M. <le...@li...> - 2007-08-30 07:20:22
|
On Thu, Aug 30, 2007 at 08:09:21AM +0100, Adrian McMenamin wrote: > On Thu, 2007-08-30 at 15:39 +0900, Paul Mundt wrote: > > In the long run these patches will have to be submitted through different > > maintainers, so the earlier they are split logically, the better. > > I will have a stab at doing this. More generally, a lot of your comments > are directed at code I inherited and I'll look at fixing them too. One > or two other things though... > The origin of the code in question has little to do with what needs to be fixed. A lot of it was crap from the beginning, that doesn't mean it doesn't have to be fixed up before it can be merged. > > > + .connect = dc_kbd_connect, > > > + .disconnect = dc_kbd_disconnect, > > > + .drv = { > > > + .name = "Dreamcast_keyboard", > > > + .bus = &maple_bus_type, > > > + .probe = probe_maple_kbd,}, > > > +}; > > > + > > I'm a bit confused as to why you don't have a registration function for a > > struct maple_driver that automatically sets the bus type? This is the > > convention most of the busses use. > > > > I'm not sure I follow what you mean - are you saying I shouldn't > initialise it with the bus type set? > Yes, you should have a maple registration function that sets the bus type for you. Most of the other busses do this. > > > --- /dev/null > > > +++ b/drivers/sh/maple/Makefile > > > @@ -0,0 +1,3 @@ > > > +#Makefile for Maple Bus > > > + > > > +obj-y := maplebus.o > > > > No module goodness? > > I can do it as a module I suppose... > Well, it can be a tristate, so obj-y is artificially limiting. > > > +/* maplebus.c > > > + * Core maple bus functionality > > > + * Core code copyright > > > + * Paul Mundt, M. R. Brown and others > > > + * Porting to 2.6 Copyright Adrian McMenamin, 2007 > > > + * Licence: GNU GPL version 2 > > > + * http://www.gnu.org > > > + */ > > > + > > Both Marcus and I intended all of our code to be v2 only, so that should > > probably be statically defined here. However, I believe Yaegashi-san > > wrote a lot of this initial version, and I'm sure there were others that > > hacked on it as well. So we may simply have to leave it as GPLv2 with the > > unfortunate + any later version garbage. > > Yes, and none of you left any copyright messages. Very poor show! > I suppose no one wanted to be associated too closely with that particular bit of code.. at least that's the excuse I'm sticking with. ;-) This is probably something you can grovel through the CVS history for, though. > > > +void maple_add_packet(struct mapleq *mq) > > > +{ > > > + unsigned long flags; > > > + > > > + local_irq_save(flags); > > > + list_add((struct list_head *) mq, &maple_waitq); > > > + local_irq_restore(flags); > > > +} > > > + > > This can use some proper locking, and the cast is pointless. mq should > > have a list_head in it somewhere that gets passed in rather than > > expecting the cast to work out. > > Actually, I'm not sure the locking is needed anymore at all - I > inherited that. But assuming a kernel thread will not be scheduled > against itself (am I safe to do that?), I cannot see how this could > executed concurrently with other code that manipulates the queue. > Yes, it should be safe to drop the irq disabling around this. Remember you also have safe iterators if you are concerned about something disappearing from the list while you are looping over it. > > > + > > > +static void maple_bus_release(struct device *dev) > > > +{ > > > + printk(KERN_INFO "Releasing maple bus device\n"); > > > +} > > > + > > Kill this. > > > > I thought busses where required to have them ... that's what my book > says. Oh well. > The release function, yes, not the printk(). > > > +/* Maple Bus command and response codes */ > > > +/* Function codes */ > > > > These can use enums and opaque types. > > These are real numbers though. > As are enums. enums are also generally more readable for these sorts of things, too. |
From: Adrian M. <ad...@ne...> - 2007-08-30 07:09:53
|
On Thu, 2007-08-30 at 15:39 +0900, Paul Mundt wrote: > On Tue, Aug 28, 2007 at 11:14:00PM +0100, Adrian McMenamin wrote: > > Please find this patch below - they said it would never be done! > > > > Anyway, this adds new maplebus support to the kernel and a maple > > keyboard driver is also attached. There a couple of minor and > > consequential patches to other kernel subsystems attached that are > > required to get this to work (eg make the PVR2 VBLANK interrupt > > shareable). > > > It would be nice if you could split this up at least, so there's the PVR2 > thing by itself, the patch adding the bus, and then the input driver > afterwards. > > In the long run these patches will have to be submitted through different > maintainers, so the earlier they are split logically, the better. > I will have a stab at doing this. More generally, a lot of your comments are directed at code I inherited and I'll look at fixing them too. One or two other things though... > > +static struct maple_driver dc_kbd_driver = { > > + .function = MAPLE_FUNC_KEYBOARD, > > + .connect = dc_kbd_connect, > > + .disconnect = dc_kbd_disconnect, > > + .drv = { > > + .name = "Dreamcast_keyboard", > > + .bus = &maple_bus_type, > > + .probe = probe_maple_kbd,}, > > +}; > > + > I'm a bit confused as to why you don't have a registration function for a > struct maple_driver that automatically sets the bus type? This is the > convention most of the busses use. > I'm not sure I follow what you mean - are you saying I shouldn't initialise it with the bus type set? > > diff --git a/drivers/sh/maple/Makefile b/drivers/sh/maple/Makefile > > new file mode 100644 > > index 0000000..f8c39f2 > > --- /dev/null > > +++ b/drivers/sh/maple/Makefile > > @@ -0,0 +1,3 @@ > > +#Makefile for Maple Bus > > + > > +obj-y := maplebus.o > > No module goodness? > I can do it as a module I suppose... > > diff --git a/drivers/sh/maple/maplebus.c b/drivers/sh/maple/maplebus.c > > new file mode 100644 > > index 0000000..fc27543 > > --- /dev/null > > +++ b/drivers/sh/maple/maplebus.c > > @@ -0,0 +1,641 @@ > > +/* maplebus.c > > + * Core maple bus functionality > > + * Core code copyright > > + * Paul Mundt, M. R. Brown and others > > + * Porting to 2.6 Copyright Adrian McMenamin, 2007 > > + * Licence: GNU GPL version 2 > > + * http://www.gnu.org > > + */ > > + > Both Marcus and I intended all of our code to be v2 only, so that should > probably be statically defined here. However, I believe Yaegashi-san > wrote a lot of this initial version, and I'm sure there were others that > hacked on it as well. So we may simply have to leave it as GPLv2 with the > unfortunate + any later version garbage. > Yes, and none of you left any copyright messages. Very poor show! > > +void maple_add_packet(struct mapleq *mq) > > +{ > > + unsigned long flags; > > + > > + local_irq_save(flags); > > + list_add((struct list_head *) mq, &maple_waitq); > > + local_irq_restore(flags); > > +} > > + > This can use some proper locking, and the cast is pointless. mq should > have a list_head in it somewhere that gets passed in rather than > expecting the cast to work out. > Actually, I'm not sure the locking is needed anymore at all - I inherited that. But assuming a kernel thread will not be scheduled against itself (am I safe to do that?), I cannot see how this could executed concurrently with other code that manipulates the queue. > > + function = be32_to_cpu(dev->devinfo.function); > > + > What exactly is the point of this? The function is big endian, really? > Err, yes. > to 1/0. > > > +static int maple_bus_uevent(struct device *dev, char **envp, > > + int num_envp, char *buffer, int buffer_size) > > +{ > > + return 0; > > +} > > How are you planning on notifying userspace when a device is > plugged/unplugged? > Device model takes care of that ... the above is pretty redundant and should go. > > + > > +static void maple_bus_release(struct device *dev) > > +{ > > + printk(KERN_INFO "Releasing maple bus device\n"); > > +} > > + > Kill this. > I thought busses where required to have them ... that's what my book says. Oh well. > > > diff --git a/include/linux/input.h b/include/linux/input.h > > index e02c6a6..2e65c88 100644 > > --- a/include/linux/input.h > > +++ b/include/linux/input.h > > @@ -688,6 +688,7 @@ struct input_absinfo { > > #define BUS_HOST 0x19 > > #define BUS_GSC 0x1A > > #define BUS_ATARI 0x1B > > +#define BUS_MAPLE 0x1C > > > Do we really need to still do this these days? > I believe so, yes. > > +/* Maple Bus command and response codes */ > > +/* Function codes */ > > These can use enums and opaque types. > These are real numbers though. > > +struct mapleq { > > +struct maple_devinfo { > [snip] > > > + char product_licence[60]; > > British variable names, if there's nothing in CodingStyle about that, > there should be :-) Not being British, what ever my passport says, I wouldn't know :) |
From: Paul M. <le...@li...> - 2007-08-30 06:41:02
|
On Tue, Aug 28, 2007 at 11:14:00PM +0100, Adrian McMenamin wrote: > Please find this patch below - they said it would never be done! > > Anyway, this adds new maplebus support to the kernel and a maple > keyboard driver is also attached. There a couple of minor and > consequential patches to other kernel subsystems attached that are > required to get this to work (eg make the PVR2 VBLANK interrupt > shareable). > It would be nice if you could split this up at least, so there's the PVR2 thing by itself, the patch adding the bus, and then the input driver afterwards. In the long run these patches will have to be submitted through different maintainers, so the earlier they are split logically, the better. > --- /dev/null > +++ b/drivers/input/keyboard/maple_keyb.c > @@ -0,0 +1,210 @@ > +/* > + * SEGA Dreamcast keyboard driver > + * Based on drivers/usb/usbkbd.c > + * Copyright YAEGASHI Takeshi, 2001 > + * Porting to 2.6 Copyright Adrian McMenamin, 2007 > + * Licensed under the GPL > + */ > + The licensing is rather ambiguous here. From the MODULE_LICENSE() we can infer that this is GPLv2 + any later version, so that's probably something that should be verbosely noted. > +MODULE_AUTHOR > + ("YAEGASHI Takeshi <t...@ke...>, Adrian McMenamin > <ad...@mc..."); This wrapping is rather broken.. > + else > + printk > + ("Unknown key (scancode %#x) released.", > + kbd->old[i]); Likewise. > + } > + > + if (kbd->new[i] > 3 > + && memchr(kbd->old + 2, kbd->new[i], 6) != NULL) { &&'s at the end of the first line. > + if (dc_kbd_keycode[kbd->new[i]]) > + input_report_key(dev, > + dc_kbd_keycode[kbd-> > + new[i]], > + 1); > + else > + printk > + ("Unknown key (scancode %#x) pressed.", > + kbd->new[i]); More strange wrapping. > + memcpy(kbd->old, kbd->new, 8); The size here should be calculated based off the size of kbd->old, rather than hard coded. If you intend to hardcode it, at least use a define to make the size descriptive. > + kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL); > + if (unlikely(!kbd)) > + return -1; > + memset(kbd, 0, sizeof(struct dc_kbd)); > + kzalloc() > + input_register_device(kbd->dev); > + This can fail. > +static struct maple_driver dc_kbd_driver = { > + .function = MAPLE_FUNC_KEYBOARD, > + .connect = dc_kbd_connect, > + .disconnect = dc_kbd_disconnect, > + .drv = { > + .name = "Dreamcast_keyboard", > + .bus = &maple_bus_type, > + .probe = probe_maple_kbd,}, > +}; > + I'm a bit confused as to why you don't have a registration function for a struct maple_driver that automatically sets the bus type? This is the convention most of the busses use. > diff --git a/drivers/sh/maple/Makefile b/drivers/sh/maple/Makefile > new file mode 100644 > index 0000000..f8c39f2 > --- /dev/null > +++ b/drivers/sh/maple/Makefile > @@ -0,0 +1,3 @@ > +#Makefile for Maple Bus > + > +obj-y := maplebus.o No module goodness? > diff --git a/drivers/sh/maple/maplebus.c b/drivers/sh/maple/maplebus.c > new file mode 100644 > index 0000000..fc27543 > --- /dev/null > +++ b/drivers/sh/maple/maplebus.c > @@ -0,0 +1,641 @@ > +/* maplebus.c > + * Core maple bus functionality > + * Core code copyright > + * Paul Mundt, M. R. Brown and others > + * Porting to 2.6 Copyright Adrian McMenamin, 2007 > + * Licence: GNU GPL version 2 > + * http://www.gnu.org > + */ > + Both Marcus and I intended all of our code to be v2 only, so that should probably be statically defined here. However, I believe Yaegashi-san wrote a lot of this initial version, and I'm sure there were others that hacked on it as well. So we may simply have to leave it as GPLv2 with the unfortunate + any later version garbage. > +static struct maple_driver maple_basic_driver; > +static struct device maple_bus; > +static int subdevice_map[MAPLE_PORTS]; > +unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; > +unsigned long maple_pnp_time; > +static int started; > +static int scanning; > + Way too many global variables. None of these need to be global, and even the statics you can likely largely do away with. > +void maple_getcond_callback(struct maple_device *dev, > + void (*callback) (struct mapleq *mq), > + unsigned long interval, unsigned long function) > +{ > + dev->callback = callback; > + dev->interval = interval; > + dev->function = cpu_to_be32(function); > + dev->when = 0; > +} > + > +EXPORT_SYMBOL(maple_getcond_callback); > + EXPORT_SYMBOL_GPL(), and no white space between that and the closing }. > +static void maple_release_device(struct device *dev) > +{ > + if (likely(dev->type)) { > + if (likely(dev->type->name)) > + kfree(dev->type->name); > + kfree(dev->type); kfree() can handle NULL, so you can just do this as: if (likely(dev->type)) { kfree(dev->type->name); kfree(dev->type); } ... > +void maple_add_packet(struct mapleq *mq) > +{ > + unsigned long flags; > + > + local_irq_save(flags); > + list_add((struct list_head *) mq, &maple_waitq); > + local_irq_restore(flags); > +} > + This can use some proper locking, and the cast is pointless. mq should have a list_head in it somewhere that gets passed in rather than expecting the cast to work out. > +static struct mapleq *maple_allocq(struct maple_device *dev) > +{ > + unsigned long buf; > + struct mapleq *mq; > + > + mq = kmalloc(sizeof(*mq), GFP_KERNEL); > + if (unlikely(!mq)) > + return NULL; > + > + mq->dev = dev; > + buf = (unsigned long) mq->buf; > + buf = (buf + 31) & ~31; > + mq->recvbuf = (void *) P2SEGADDR(buf); > + This is a serious hack. I would suggest just using a slab cache for these objects, and forcing cacheline alignment there. Then you can also set up the uncached recvbuf in the slab ctor. > + function = be32_to_cpu(dev->devinfo.function); > + What exactly is the point of this? The function is big endian, really? > +static int maple_get_dma_buffer(void) > +{ > + maple_sendbuf = > + (void *) __get_dma_pages(GFP_KERNEL, MAPLE_DMA_PAGES); > + if (unlikely(!maple_sendbuf)) > + return -ENOMEM; > + memset(maple_sendbuf, 0, MAPLE_DMA_SIZE); > + return 0; > +} > + __get_free_pages(GFP_KERNEL | __GFP_ZERO, MAPLE_DMA_ORDER); ... We don't even have a ZONE_DMA, so __get_dma_pages() is total brain-damage. > + maple_drv = container_of(drvptr, struct maple_driver, drv); > + maple_dev = container_of(devptr, struct maple_device, dev); > + > + if (unlikely > + (maple_dev->devinfo. > + function & be32_to_cpu(maple_drv->function))) > + return 1; > + return 0; Strange wrapping, and you can just do the return of that check directly, rather than breaking this out in to 1/0. > +static int maple_bus_uevent(struct device *dev, char **envp, > + int num_envp, char *buffer, int buffer_size) > +{ > + return 0; > +} How are you planning on notifying userspace when a device is plugged/unplugged? > + > +static void maple_bus_release(struct device *dev) > +{ > + printk(KERN_INFO "Releasing maple bus device\n"); > +} > + Kill this. > +static struct maple_driver maple_basic_driver = { > + .drv = { > + .name = "Maple_bus_basic_driver", > + .bus = &maple_bus_type,}, Strange brace cuddling. Even stranger driver name. > +static struct device maple_bus = { > + .bus_id = "maple0", > + .release = maple_bus_release, > +}; > + What is the 0 for? > + retval = device_register(&maple_bus); > + if (unlikely(retval)) > + goto cleanup; > + > + retval = bus_register(&maple_bus_type); > + if (unlikely(retval)) > + goto cleanup_device; > + > + printk(KERN_INFO "Maple bus core now registered.\n"); > + > + retval = driver_register(&maple_basic_driver.drv); > + if (unlikely(retval)) > + goto cleanup_bus; > + > + /* allocate memory for maple bus dma */ > + retval = maple_get_dma_buffer(); > + if (unlikely(retval)) { > + printk(KERN_INFO > + "Maple bus: Failed to allocate Maple DMA buffers\n"); > + goto cleanup_basic; > + } > + > + /* set up DMA interrupt handler */ > + retval = maple_set_dma_interrupt_handler(); > + if (unlikely(retval)) { > + printk(KERN_INFO > + "Maple bus: Failed to grab maple DMA IRQ\n"); > + goto cleanup_dma; > + } > + > + /* set up VBLANK interrupt handler */ > + retval = maple_set_vblank_interrupt_handler(); > + if (unlikely(retval)) { > + printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n"); > + goto cleanup_irq; > + } > + > + > + /* setup maple ports */ > + for (i = 0; i < MAPLE_PORTS; i++) { > + mdev = maple_alloc_dev(i, 0); > + mdev->registered = 0; > + if (unlikely(!mdev)) > + goto cleanup_bothirqs; i-1 mdev allocations will leak on failure. You've also just oopsed on the ->registered dereference if the allocation fails. > +static void __exit maple_bus_exit(void) > +{ > + driver_unregister(&maple_basic_driver.drv); > + bus_unregister(&maple_bus_type); > + > + if (likely(maple_sendbuf)) > + free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); > + > + free_irq(HW_EVENT_MAPLE_DMA, 0); > + free_irq(HW_EVENT_VSYNC, 0); I would do these first. Bad things will happen if all of your state disappears whilst IRQs are still in-flight. > +/* use init call to ensure bus is registered ahead of devices */ > +fs_initcall(maple_bus_init); Use subsys_initcall() here, it's a subsystem, so this is entirely reasonable. > diff --git a/include/linux/input.h b/include/linux/input.h > index e02c6a6..2e65c88 100644 > --- a/include/linux/input.h > +++ b/include/linux/input.h > @@ -688,6 +688,7 @@ struct input_absinfo { > #define BUS_HOST 0x19 > #define BUS_GSC 0x1A > #define BUS_ATARI 0x1B > +#define BUS_MAPLE 0x1C > Do we really need to still do this these days? > +/* Maple Bus command and response codes */ > +/* Function codes */ These can use enums and opaque types. > +struct mapleq { > + struct list_head list; > + struct maple_device *dev; > + void *sendbuf, *recvbuf; > + unsigned char command, length; > + unsigned char buf[1024 + 32]; > +}; > + That's pretty big not to be dynamically allocating. > +struct maple_devinfo { [snip] > + char product_licence[60]; British variable names, if there's nothing in CodingStyle about that, there should be :-) |
From: Paul M. <le...@li...> - 2007-08-30 00:03:54
|
On Wed, Aug 29, 2007 at 06:06:00PM -0700, Kristoffer Ericson wrote: > On Wed, 29 Aug 2007 18:09:47 +0900 > Paul Mundt <le...@li...> wrote: > > > On Tue, Aug 28, 2007 at 08:03:50PM -0700, Kristoffer Ericson wrote: > > > The hd64461 have two slots (CF/PCMCIA) but since CF is handled by > > > libata (and initial start in hd64461.c) should this driver be able to > > > handle both CF and PCMCIA? > > > > > > Personally i feel it would make more sense if it only controlled the > > > pcmcia. Anyone wanting CF support could easily add that for their > > > platform. > > > > > > Before we never used the CF slot but instead let ide-sh handle it. > > > > > I'm not sure I understand your question. HD64461 is a multi-function > > device, meaning that you have a driver for each defined function. Usually > > these need to chain in to the MFD driver for things like IRQ demux and > > things like that, but each function is generally wholly isolated. > I put my words poorly, what I ment was, is it resonable that the hd64461_SS driver should > handle the CF slot aswell as the pcmcia one? > Currently its set to only handle the pcmcia, but you can through menuconfig make it also > control the CF slot. > For storage devices it doesn't really matter, but keep in mind that there are also non-storage CF devices, so you may want to handle both cases. I would focus on PCMCIA first and worry about the corner cases later, however. |
From: Paul M. <le...@li...> - 2007-08-29 23:56:19
|
On Wed, Aug 29, 2007 at 04:36:37PM +0200, EXTERNAL Brunner Markus (Praktikant; ST-FIR/Eng) wrote: > why isn't /dev/rtc the well known "c 10 135" device that it's on x86, > but a magic undocumented "c 254 0" device? > Devices.txt lists this major number as LOCAL/EXPERIMENTAL USE. > This is a bit of an intentional namespace conflict. The 10 135 device is a legacy driver, and even x86 is moving away from that in favour of dynamic numbers. The new drivers/rtc/ subsystem is entirely dynamic, so all of the architectures using this behave the same way. Static device nodes are a relic of the past, and new system designs should not depend on them. Even without udev, you can still get a link to the device node via sysfs, so it's possible to script around this, but you really should be using udev. hwclock and friends generally work transparently regardless of whether the legacy driver is in use or not. |
From: Kristoffer E. <kri...@gm...> - 2007-08-29 16:06:10
|
On Wed, 29 Aug 2007 18:09:47 +0900 Paul Mundt <le...@li...> wrote: > On Tue, Aug 28, 2007 at 08:03:50PM -0700, Kristoffer Ericson wrote: > > The hd64461 have two slots (CF/PCMCIA) but since CF is handled by > > libata (and initial start in hd64461.c) should this driver be able to > > handle both CF and PCMCIA? > > > > Personally i feel it would make more sense if it only controlled the > > pcmcia. Anyone wanting CF support could easily add that for their > > platform. > > > > Before we never used the CF slot but instead let ide-sh handle it. > > > I'm not sure I understand your question. HD64461 is a multi-function > device, meaning that you have a driver for each defined function. Usually > these need to chain in to the MFD driver for things like IRQ demux and > things like that, but each function is generally wholly isolated. I put my words poorly, what I ment was, is it resonable that the hd64461_SS driver should handle the CF slot aswell as the pcmcia one? Currently its set to only handle the pcmcia, but you can through menuconfig make it also control the CF slot. > > See things like drivers/mfd/sm501.c and friends for how to work with this > sort of stuff from the driver model. The PCMCIA function of HD64461 has > nothing to do with the CF/pata_platform integration, and it's handled > through an entirely different driver. HD64465 is the same. |
From: Mike F. <va...@ge...> - 2007-08-29 14:50:47
|
On Wednesday 29 August 2007, EXTERNAL Brunner Markus (Praktikant; ST-FIR/En= g)=20 wrote: > why isn't /dev/rtc the well known "c 10 135" device that it's on x86, > but a magic undocumented "c 254 0" device? > Devices.txt lists this major number as LOCAL/EXPERIMENTAL USE. a follow up i should have included originally ... what rtc driver are you=20 using ? =2Dmike |
From: Mike F. <va...@ge...> - 2007-08-29 14:45:27
|
On Wednesday 29 August 2007, EXTERNAL Brunner Markus (Praktikant; ST-FIR/En= g)=20 wrote: > why isn't /dev/rtc the well known "c 10 135" device that it's on x86, just because x86 has crap doesnt mean everyone else needs to suffer > but a magic undocumented "c 254 0" device? > Devices.txt lists this major number as LOCAL/EXPERIMENTAL USE. it's magic because it's dynamic properly architected systems should not know/care what the major/minor numb= ers=20 are =2Dmike |
From: EXTERNAL B. M. (P. ST-FIR/Eng) <ext...@de...> - 2007-08-29 14:36:49
|
Hi, why isn't /dev/rtc the well known "c 10 135" device that it's on x86, but a magic undocumented "c 254 0" device?=20 Devices.txt lists this major number as LOCAL/EXPERIMENTAL USE.=20 Regards Markus |
From: Mike F. <va...@ge...> - 2007-08-29 11:27:37
|
On Wednesday 29 August 2007, Adrian McMenamin wrote: > On Wed, August 29, 2007 2:36 am, Mike Frysinger wrote: > > On Tuesday 28 August 2007, Adrian McMenamin wrote: > >> --- /dev/null > >> +++ b/drivers/input/keyboard/maple_keyb.c > >> @@ -0,0 +1,210 @@ > >> +/* > >> + * SEGA Dreamcast keyboard driver > >> + * Based on drivers/usb/usbkbd.c > >> + * Copyright YAEGASHI Takeshi, 2001 > >> + * Porting to 2.6 Copyright Adrian McMenamin, 2007 > >> + * Licensed under the GPL > > > > you mean GPL-2 [or later] ? > > Actually, I don't know. The original just said "GPL" and as it was > submitted to the kernel we can assume it's at least v2 but there was no > additional specification given. Shall I just leave it as is? if the old file only said "Licensed under the GPL" then i guess you dont ha= ve=20 much choice without contacting the people who wrote the original > >> +static struct maple_driver dc_kbd_driver =3D { > >> + .function =3D MAPLE_FUNC_KEYBOARD, > >> + .connect =3D dc_kbd_connect, > >> + .disconnect =3D dc_kbd_disconnect, > >> + .drv =3D { > >> + .name =3D "Dreamcast_keyboard", > >> + .bus =3D &maple_bus_type, > >> + .probe =3D probe_maple_kbd,}, > > > > that last "}," shouldnt be cuddled like that > > Really? It's what i've used before and it has been accepted into the > kernel. > > Should it be > .probe =3D probe_maple_kbd, > }, > > then? =2Edev =3D { .moo =3D cow, .foo =3D bar, }, > >> +/* use init call to ensure bus is registered ahead of devices */ > >> +fs_initcall(maple_bus_init); > > > > thought subsys_initcall() was what you wanted ? > > I thought it would be better behaved to use a later call and as this is fs > related (sys) it seemed appropriate. If this a faux pas I can change it... Paul would know =2Dmike |