Hi, I wrote a simple module, which should initialise an USART in RS485-mode (RTS stays low after initialisation) and register it as platform_device. Its on an Atmel at91sam9260 board, so I can re-use most of the mach arm-sources (atmel_serial.c etc.) When the module gets loaded I got the following output $ modprobe axm_rs485_uart Original ATMEL_US_MR=0 Write 1 to ATMEL_US_MR After Write ATMEL_US_MR=0 axm_rs485_uart: registering uart port #3 in RS485 mode as atmel_usart3 - read the actual state from the USART Mode Register - Put the mode into RS485 mode ("or" a bit) - write the new mode into the register - read the register again...and (what a surprise) see, that the write operation didn't succeed A simple write to a register seems to fail. In consequence the RTS line gets high after the Pin has been "muxed" to its RTS-Rolle with at91_set_B_periph(). I think, that I'm doing something wrong with request_mem() and ioremap() No clue what? Can you help me with this? Thanks for any advice. Regards maurus #include <linux/errno.h> #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/atmel_serial.h> #include <mach/board.h> #define UART_PORT_WITH_RTS_MAX 4 #define UART_PORT_DEFAULT 3 #define UART_PORT_DEFAULT_DEVICE_NAME "atmel_usart3" // USART ids / interrupts static u32 at91sam9260_id_us[UART_PORT_WITH_RTS_MAX] = { AT91SAM9260_ID_US0, AT91SAM9260_ID_US1, AT91SAM9260_ID_US2, AT91SAM9260_ID_US3 }; #define A_PERIPHERAL 0 #define B_PERIPHERAL 1 struct io_mux_pin { u32 io_line_addr; // I/O Line address uint peripheral; // A or B Peripheral } io_mux_pin; struct io_mux_pin at91_rts_io_pin[UART_PORT_WITH_RTS_MAX] = { { AT91_PIN_PB26, A_PERIPHERAL }, //RTS0 { AT91_PIN_PB28, A_PERIPHERAL }, //RTS1 { AT91_PIN_PA4, A_PERIPHERAL }, //RTS2 { AT91_PIN_PC8, B_PERIPHERAL } //RTS3 }; //Define some module information. MODULE_AUTHOR("Maus"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Initialize UART port in RS485 mode. RTS-Line stays low.") ; // Stores our pointer to the platform device, needed for release during exit. static struct platform_device *pdev; // Remapped virtual base address static void *vbaseaddr; // get port_number as parameter, available in sysfs // valid value from 0 to UART_PORT_MAX static uint uart_port = UART_PORT_DEFAULT; module_param( uart_port, uint, 0400 ); MODULE_PARM_DESC(uart_port, "UART port number to initialize in RS485 mode [0-" __MODULE_STRING(UART_PORT_WITH_RTS_MAX)"]"); // get device_name as parameter, available in sysfs static char device_name[30] = UART_PORT_DEFAULT_DEVICE_NAME; module_param_string( device_name, device_name, sizeof(device_name), 0400 ); /* * Register UARTX as platform device. */ static int __init axm_rs485_uart_init(void) { int retValue = 0; unsigned mode; //check parameter input if (uart_port >= UART_PORT_WITH_RTS_MAX) { printk(KERN_ERR "%s: uart_port=%u must be below %u\n", THIS_MODULE->name, uart_port, UART_PORT_WITH_RTS_MAX); return -EINVAL; } /* * Get platform_device struct from exported at91_register_uart * * - Don't configure RTS pin. * - portnr = uart_port+1 (not necessary due call after boot-up) */ pdev = at91_register_uart(at91sam9260_id_us[uart_port], uart_port + 1, ATMEL_UART_CTS); if (pdev == NULL) { printk(KERN_ERR "%s: unable to register uart%u\n", THIS_MODULE->name, uart_port); return -EINVAL; } //set platform_device_name according parameter or default value if (!strcmp(pdev->name, device_name)) { pdev->name = device_name; //correct the device id pdev->id = uart_port; } //if (!request_mem_region(at91sam9260_base_us[uart_port], SZ_16K , THIS_MODULE->name)) if (!request_mem_region(pdev->resource[0].start,pdev->resource[0].end- pdev->resource[0].start , THIS_MODULE->name)) { printk(KERN_ERR "%s: unable to request memory region for uart%u \n", THIS_MODULE->name, uart_port); goto out_direct; } vbaseaddr = ioremap(pdev->resource[0].start,pdev->resource[0].end- pdev->resource[0].start); if (!vbaseaddr) { goto out_reqmem_io_pin; } mode =readl(vbaseaddr + ATMEL_US_MR); printk("Original ATMEL_US_MR=%lX\n", mode); mode |= ATMEL_US_USMODE_RS485; printk("Write %lX to ATMEL_US_MR\n", mode); /* put USART to RS485 mode */ writel(mode, vbaseaddr + ATMEL_US_MR); /*check if mode has been written to register*/ mode = readl(vbaseaddr + ATMEL_US_MR); printk("After Write ATMEL_US_MR=%lX\n", mode); /* release all resources to be used by other drivers */ iounmap(vbaseaddr); release_mem_region( pdev->resource[0].start, pdev->resource[0].end- pdev->resource[0].start); /* Decide whether pin is A or B peripheral and configure RTS pin to stay low */ if (at91_rts_io_pin[uart_port].peripheral == A_PERIPHERAL) { at91_set_A_periph(at91_rts_io_pin[uart_port].io_line_addr, 0); } else { at91_set_B_periph(at91_rts_io_pin[uart_port].io_line_addr, 0); } retValue = platform_device_register(pdev); if (retValue) { printk(KERN_ERR "%s: unable to register platform device\n", THIS_MODULE->name); return -EINVAL; } printk(KERN_NOTICE "%s: registering uart port #%u in RS485 mode as %s\n", THIS_MODULE->name, uart_port, device_name); return retValue; out_reqmem_io_pin: release_mem_region( pdev->resource[0].start, pdev->resource[0].end- pdev->resource[0].start); out_direct: return -EINVAL; } /* * Release (unregister device) UART */ static void __exit axm_rs485_uart_exit(void) { if (pdev != NULL) { platform_device_unregister(pdev); } printk(KERN_NOTICE "%s: releasing USART \n", THIS_MODULE->name); } module_init(axm_rs485_uart_init); module_exit(axm_rs485_uart_exit); _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies