rio-access.c revision ad1e9380b17addf112f89ce5a57d4d0bee129b7a
1394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter/* 2394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * RapidIO configuration space access support 3394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * 4394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Copyright 2005 MontaVista Software, Inc. 5394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Matt Porter <mporter@kernel.crashing.org> 6394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * 7394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * This program is free software; you can redistribute it and/or modify it 8394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * under the terms of the GNU General Public License as published by the 9394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Free Software Foundation; either version 2 of the License, or (at your 10394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * option) any later version. 11394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter */ 12394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 13394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#include <linux/rio.h> 14394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#include <linux/module.h> 15394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 16394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter/* 17394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * These interrupt-safe spinlocks protect all accesses to RIO 18394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * configuration space and doorbell access. 19394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter */ 2034af946a22724c4e2b204957f2b24b22a0fb121cIngo Molnarstatic DEFINE_SPINLOCK(rio_config_lock); 2134af946a22724c4e2b204957f2b24b22a0fb121cIngo Molnarstatic DEFINE_SPINLOCK(rio_doorbell_lock); 22394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 23394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter/* 24394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Wrappers for all RIO configuration access functions. They just check 25394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * alignment, do locking and call the low-level functions pointed to 26394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * by rio_mport->ops. 27394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter */ 28394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 29394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#define RIO_8_BAD 0 30394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#define RIO_16_BAD (offset & 1) 31394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#define RIO_32_BAD (offset & 3) 32394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 33394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter/** 34394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * RIO_LOP_READ - Generate rio_local_read_config_* functions 35394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @size: Size of configuration space read (8, 16, 32 bits) 36394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @type: C type of value argument 37394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @len: Length of configuration space read (1, 2, 4 bytes) 38394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * 39394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Generates rio_local_read_config_* functions used to access 40394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * configuration space registers on the local device. 41394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter */ 42394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#define RIO_LOP_READ(size,type,len) \ 43394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porterint __rio_local_read_config_##size \ 44394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter (struct rio_mport *mport, u32 offset, type *value) \ 45394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter{ \ 46394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter int res; \ 47394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter unsigned long flags; \ 48394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter u32 data = 0; \ 49394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ 50394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_lock_irqsave(&rio_config_lock, flags); \ 51ad1e9380b17addf112f89ce5a57d4d0bee129b7aZhang Wei res = mport->ops->lcread(mport, mport->id, offset, len, &data); \ 52394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter *value = (type)data; \ 53394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_unlock_irqrestore(&rio_config_lock, flags); \ 54394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter return res; \ 55394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter} 56394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 57394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter/** 58394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * RIO_LOP_WRITE - Generate rio_local_write_config_* functions 59394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @size: Size of configuration space write (8, 16, 32 bits) 60394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @type: C type of value argument 61394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @len: Length of configuration space write (1, 2, 4 bytes) 62394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * 63394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Generates rio_local_write_config_* functions used to access 64394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * configuration space registers on the local device. 65394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter */ 66394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#define RIO_LOP_WRITE(size,type,len) \ 67394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porterint __rio_local_write_config_##size \ 68394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter (struct rio_mport *mport, u32 offset, type value) \ 69394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter{ \ 70394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter int res; \ 71394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter unsigned long flags; \ 72394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ 73394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_lock_irqsave(&rio_config_lock, flags); \ 74ad1e9380b17addf112f89ce5a57d4d0bee129b7aZhang Wei res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\ 75394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_unlock_irqrestore(&rio_config_lock, flags); \ 76394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter return res; \ 77394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter} 78394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 79394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_LOP_READ(8, u8, 1) 80394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_LOP_READ(16, u16, 2) 81394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_LOP_READ(32, u32, 4) 82394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_LOP_WRITE(8, u8, 1) 83394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_LOP_WRITE(16, u16, 2) 84394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_LOP_WRITE(32, u32, 4) 85394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 86394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(__rio_local_read_config_8); 87394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(__rio_local_read_config_16); 88394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(__rio_local_read_config_32); 89394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(__rio_local_write_config_8); 90394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(__rio_local_write_config_16); 91394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(__rio_local_write_config_32); 92394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 93394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter/** 94394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * RIO_OP_READ - Generate rio_mport_read_config_* functions 95394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @size: Size of configuration space read (8, 16, 32 bits) 96394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @type: C type of value argument 97394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @len: Length of configuration space read (1, 2, 4 bytes) 98394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * 99394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Generates rio_mport_read_config_* functions used to access 100394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * configuration space registers on the local device. 101394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter */ 102394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#define RIO_OP_READ(size,type,len) \ 103394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porterint rio_mport_read_config_##size \ 104394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \ 105394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter{ \ 106394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter int res; \ 107394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter unsigned long flags; \ 108394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter u32 data = 0; \ 109394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ 110394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_lock_irqsave(&rio_config_lock, flags); \ 111ad1e9380b17addf112f89ce5a57d4d0bee129b7aZhang Wei res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \ 112394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter *value = (type)data; \ 113394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_unlock_irqrestore(&rio_config_lock, flags); \ 114394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter return res; \ 115394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter} 116394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 117394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter/** 118394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * RIO_OP_WRITE - Generate rio_mport_write_config_* functions 119394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @size: Size of configuration space write (8, 16, 32 bits) 120394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @type: C type of value argument 121394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @len: Length of configuration space write (1, 2, 4 bytes) 122394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * 123394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Generates rio_mport_write_config_* functions used to access 124394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * configuration space registers on the local device. 125394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter */ 126394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter#define RIO_OP_WRITE(size,type,len) \ 127394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porterint rio_mport_write_config_##size \ 128394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \ 129394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter{ \ 130394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter int res; \ 131394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter unsigned long flags; \ 132394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ 133394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_lock_irqsave(&rio_config_lock, flags); \ 134ad1e9380b17addf112f89ce5a57d4d0bee129b7aZhang Wei res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \ 135394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_unlock_irqrestore(&rio_config_lock, flags); \ 136394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter return res; \ 137394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter} 138394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 139394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_OP_READ(8, u8, 1) 140394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_OP_READ(16, u16, 2) 141394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_OP_READ(32, u32, 4) 142394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_OP_WRITE(8, u8, 1) 143394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_OP_WRITE(16, u16, 2) 144394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterRIO_OP_WRITE(32, u32, 4) 145394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 146394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(rio_mport_read_config_8); 147394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(rio_mport_read_config_16); 148394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(rio_mport_read_config_32); 149394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(rio_mport_write_config_8); 150394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(rio_mport_write_config_16); 151394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(rio_mport_write_config_32); 152394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 153394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter/** 154394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * rio_mport_send_doorbell - Send a doorbell message 155394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * 156394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @mport: RIO master port 157394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @destid: RIO device destination ID 158394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * @data: Doorbell message data 159394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * 160394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * Send a doorbell message to a RIO device. The doorbell message 161394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter * has a 16-bit info field provided by the data argument. 162394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter */ 163394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porterint rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data) 164394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter{ 165394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter int res; 166394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter unsigned long flags; 167394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 168394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_lock_irqsave(&rio_doorbell_lock, flags); 169ad1e9380b17addf112f89ce5a57d4d0bee129b7aZhang Wei res = mport->ops->dsend(mport, mport->id, destid, data); 170394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter spin_unlock_irqrestore(&rio_doorbell_lock, flags); 171394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 172394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter return res; 173394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter} 174394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt Porter 175394b701ce4fbfde919a9bcbf84cb4820a7c6d47cMatt PorterEXPORT_SYMBOL_GPL(rio_mport_send_doorbell); 176