----------------------------------------------------------------
	Device glue driver
----------------------------------------------------------------

* What is this?

    This is a driver "devglue" that manages resources (registers, interrupts
    and clocks) based on the information described by device-tree.

    Clocks make enable when this driver is probed. Registers and interrupts
    are controlled by APIs of this driver.

    NOTICE: The devglue follows GNU Public License version 2.
            Using the devglue driver to handle the license and the other
            restrictions illegally is PROHIBITTED.

* API functions

1. character device

struct device **devglue_alloc_device(
		const char *devicepath,
		unsigned int num,
		unsigned int devno,
		const struct file_operations *fops
	)

    allocate character devices and create device files on devtmpfs

    - devicepath:
	path-name of the device files on /dev
	The maximum length of path-name is restricted to 256.
    - num:
	a number of minor device to allocate
	The maximum number of 'num' is restricted to 1024.
    - devno:
	major number of device file to specify,
	decide it automatically if zero
    - fops:
	function definitions of file operations,
	refer to "struct file_operations"

    - return value:
	array of pointers to "struct device" if positive value,
	otherwise error with the following values
		-ENODEV: devglue is not probed
		-EINVAL: invalid arguments
		-ENOMEM: lack of memory

void devglue_free_device(
		struct device **devp
	)

    destroy character devices and remove device files on devtmpfs

    - devp:
	array of pointers to "struct device" obtained from
	devglue_alloc_device()

    - return value:
	none

2. I/O area mapping

void __iomem *devglue_ioremap(
		const char *name,
		enum devglue_memory_type type
	)

    map the area associoated with a name defined on device-tree

    - name:
	name of the area defined on "reg-names"
    - type:
	type of mapping the area, taking the following value
		DEVGLUE_MEMORY_WC: uncached normal memory
		DEVGLUE_MEMORY_NC: device memory

    - return value:
	mapped virtual address if positive value,
	otherwise error with the following values
		-ENODEV: devglue is not probed
		-EINVAL: invalid arguments

    ** Refer to ARM Architecture Referemce Manual for the meaning of
       memory type.

void devglue_iounmap(
		void __iomem *vbase
	)

    release the area mapped with devglue_ioremap()

    - vbase:
	mapped virtual address obtained from devglue_ioremap()

    - return value:
	none

int devglue_reg_get_byname(
		const char *name,
		phys_addr_t *pbase,
		size_t *size
	)

    gets physical address and size of the area associated with a name.

    - name:
	name of the area defined on "reg-names"
    - pbase:
	pointer to the valiable for physical base address associated with
	'name' (Output)
    - size:
	pointer to the valiable for size associated with 'name' (Output)

    - return value:
	zero if success, otherwise error with the following values
		-ENODEV: devglue is not probed.
		-EINVAL: invalid arguments

3. interrupts

int devglue_request_irq(
		unsigned int hwirq,
		irq_handler_t handler,
		unsigned long flags,
		void *dev_id
	)

    requests the interrupt. This function is compatible with request_irq().

    - hwirq:
	interrupt number of hardware
    - handler:
	pointer to the handler function called when the interrupt occurs
    - flags:
	interrupt flags or zero
		IRQF_SHARED: interrupt is shared
    - dev_id:
	value that deliver to the handler function
	It's used for identifying shared interrupts.

    - return value:
	zero if success, otherwise error with the following values
		-ENODEV: devglue is not probed.
		-EINVAL: invalid arguments

int devglue_request_irq_byname(
		unsigned int *hwirqp,
		irq_handler_t handler,
		unsigned long flags,
		const char *name,
		void *dev_id
	)

    requests the interrupt associated with a name, and is same action as
    request_irq().

    - hwirqp:
	pointer reterned inteerupt number of hardware in
    - handler:
	pointer to the handler function called when the interrupt occurs
    - flags:
	interrupt flags or zero
		IRQF_SHARED: interrupt is shared
    - name:
	name of the interrupt defined on "interrupt-names"
    - dev_id:
	value that delivers to the handler function
	It's used for identifying shared interrupts.

    - return value:
	zero if success, otherwise error with the following values
		-ENODEV: devglue is not probed.
		-EINVAL: invalid arguments

void devglue_free_irq(
		unsigned int hwirq,
		void *dev_id
	)

    unregisters the interrupt. The function is compatible with free_irq().

    - dev_id:
	value that delivers to the handler function
	It's used for identifying shared interrupts.

    - return value:
	none

void devglue_enable_irq(
		unsigned int hwirq
	)

    enables the interrupt. The function is compatible with enable_irq().
    If the interrupt is not requested yet, enable it when requested

    - hwirq:
	interrupt number of hardware

    - return value:
	none

void devglue_enable_irq_byname(
		const char *name
	)

    enables the interrupt associated with a name, and is same action as
    enable_irq(). If the interrupt is not requested yet, enable it when
    requested.

    - name:
	name of the interrupt defined on "interrupt-names"

    - return value:
	none

void devglue_disable_irq(
		unsigned int hwirq
	)

    disables the interrupt, compatible with disable_irq().
    If the interrupt is not requested yet, disable it when requested.

    - hwirq:
	interrupt number of hardware

    - return value:
	none

void devglue_disable_irq_byname(
		const char *name
	)

    disables interrupt associated with a name, same action as disable_irq().
    If the interrupt is not requested, disable it when requested.

    - name:
	name of the interrupt defined on "interrupt-names"

    - return value:
	none

int devglue_irq_get(
		unsigned int hwirq
	)

    gets interrupt index number from hardware interrupt number.
    Interrupt index number is used for interrupt APIs on the kernel.

    - hwirq:
	interrupt number of hardware

    - return value:
	interrupt index number if success, otherwise error with the following
	values:
		-ENODEV: devglue is not probed.
		-EINVAL: invalid arguments

int devglue_irq_get_byname(
		const char *name
	)

    gets interrupt index number associated with a name.
    Interrupt index number is used for interrupt APIs on the kernel.

    - name:
	name of the interrupt defined on "interrupt-names"

    - return value:
	interrupt index number if success, otherwise error with the following
	values:
		-ENODEV: devglue is not probed.
		-EINVAL: invalid arguments

* avaiable properties of device tree

The devglue recognizes 'devglue' node and resource values included in it.
The properties for devglue are the following:

    - "compatible":
	identification strings, the following strings are available.
		"socionext,devglue"

    - reg-names:
	register names collesponding to "reg"

    - reg:
	2- or 4-tuples of the values, start address and size of I/O area
	to map
	2-tuples shows 32bit addresses, and 4-tupples shows 64bit addresses.

    - interrupt-names:
	interrupt names collesponding to "interrupts"

    - interrupts:
	3-tuple of the values, <A B C>
		A: type of interrupt (0:SPI, 1:PPI),
		B: hardware interrupt number (begin with zero),
		C: edge/level condition (4:Level, 1:Edge)

    - clock-names:
	clock names collesponding to "clocks"

    - clocks:
	clock handle defined on another block, clk driver need to support it.

	** The name string of length is limited to 16 (defined as
	   DEVGLUE_MAX_NAMELEN).
	** The devglue node exists only one.

* example of device tree

----------------------------------------------------------------
&soc {
	devglue {
		compatible = "socionext,devglue";
		reg-names = "exiv", "hdmirx0", "hdmirx1", "hdmitx0", "hdmitx1";
		reg = <0x57920000 0x1000>,
		      <0x57940000 0x2000>,
		      <0x57950000 0x2000>,
		      <0x57947000 0x100>,
		      <0x57957000 0x100>;
		interrupt-names = "vout6", "edprx0", "edprx1";
		interrupts = <0 148 4>,		/* vout6  */
		             <0 104 4>,		/* edprx0 */
		             <0 105 4>,		/* edprx1 */
		             <0 246 4>,		/* (no name) */
		             <0 247 4>,		/* (no name) */
		             <0 248 4>,		/* (no name) */
		             <0 249 4>,		/* (no name) */
		             <0 250 4>,		/* (no name) */
		             <0 251 4>,		/* (no name) */
		             <0 252 4>,		/* (no name) */
		             <0 253 4>,		/* (no name) */
		             <0 254 4>,		/* (no name) */
		             <0 255 4>;		/* (no name) */
		clock-names = "exiv";
		clocks = <&sysctrl 30>;
	};
};
----------------------------------------------------------------
