diff options
author | Christian Gromm <christian.gromm@microchip.com> | 2016-08-02 11:48:39 +0200 |
---|---|---|
committer | Gerrit Code Review <gerrit@172.30.200.200> | 2016-08-04 07:17:20 +0000 |
commit | 7b58e8b4d4cd279b00124e50cbbc70b01248a0ee (patch) | |
tree | 3387ff74f5957fabe01a26f683ae84813436d32a /recipes-kernel/hdm-dim2 | |
parent | 7e3a1a0442347e0290133707aa70e207bce47a99 (diff) |
recipes-kernel: update driver recipes
This patch changes the recipes to fetch the driver sources from
AGL's src directory. It therefore removes the redundant source
files from the recipe directory.
Change-Id: Ib3c48a0c7e79144713ccd8e10a89185cd929b41c
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
(cherry picked from commit 1ea0cef6934ccadc36395b60d8b8d58d69016e28)
Diffstat (limited to 'recipes-kernel/hdm-dim2')
-rw-r--r-- | recipes-kernel/hdm-dim2/files/COPYING | 340 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/Makefile | 18 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/dim2_errors.h | 65 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/dim2_hal.c | 894 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/dim2_hal.h | 116 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/dim2_hdm.c | 933 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/dim2_hdm.h | 27 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/dim2_reg.h | 173 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/dim2_sysfs.c | 117 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/files/dim2_sysfs.h | 36 | ||||
-rw-r--r-- | recipes-kernel/hdm-dim2/hdm-dim2.bb | 27 |
11 files changed, 7 insertions, 2739 deletions
diff --git a/recipes-kernel/hdm-dim2/files/COPYING b/recipes-kernel/hdm-dim2/files/COPYING deleted file mode 100644 index 6d45519c8..000000000 --- a/recipes-kernel/hdm-dim2/files/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - 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, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/recipes-kernel/hdm-dim2/files/Makefile b/recipes-kernel/hdm-dim2/files/Makefile deleted file mode 100644 index a9dc62ab0..000000000 --- a/recipes-kernel/hdm-dim2/files/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# Makefile -# - -SRC := $(shell pwd) - -obj-m += hdm_dim2.o -hdm_dim2-y := dim2_hdm.o dim2_hal.o dim2_sysfs.o -CFLAGS_dim2_hdm.o := -I$(src)/../../mostcore/files -I$(src)/../../aim-network/files - -all: - $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules - -modules_install: - $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install - -clean: - $(MAKE) -C $(KERNEL_SRC) M=$(SRC) clean - diff --git a/recipes-kernel/hdm-dim2/files/dim2_errors.h b/recipes-kernel/hdm-dim2/files/dim2_errors.h deleted file mode 100644 index 5a713df1d..000000000 --- a/recipes-kernel/hdm-dim2/files/dim2_errors.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * dim2_errors.h - Definitions of errors for DIM2 HAL API - * (MediaLB, Device Interface Macro IP, OS62420) - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. - */ - -#ifndef _MOST_DIM_ERRORS_H -#define _MOST_DIM_ERRORS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * MOST DIM errors. - */ -enum dim_errors_t { - /** Not an error */ - DIM_NO_ERROR = 0, - - /** Bad base address for DIM2 IP */ - DIM_INIT_ERR_DIM_ADDR = 0x10, - - /**< Bad MediaLB clock */ - DIM_INIT_ERR_MLB_CLOCK, - - /** Bad channel address */ - DIM_INIT_ERR_CHANNEL_ADDRESS, - - /** Out of DBR memory */ - DIM_INIT_ERR_OUT_OF_MEMORY, - - /** DIM API is called while DIM is not initialized successfully */ - DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20, - - /** - * Configuration does not respect hardware limitations - * for isochronous or synchronous channels - */ - DIM_ERR_BAD_CONFIG, - - /** - * Buffer size does not respect hardware limitations - * for isochronous or synchronous channels - */ - DIM_ERR_BAD_BUFFER_SIZE, - - DIM_ERR_UNDERFLOW, - - DIM_ERR_OVERFLOW, -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _MOST_DIM_ERRORS_H */ diff --git a/recipes-kernel/hdm-dim2/files/dim2_hal.c b/recipes-kernel/hdm-dim2/files/dim2_hal.c deleted file mode 100644 index 172257596..000000000 --- a/recipes-kernel/hdm-dim2/files/dim2_hal.c +++ /dev/null @@ -1,894 +0,0 @@ -/* - * dim2_hal.c - DIM2 HAL implementation - * (MediaLB, Device Interface Macro IP, OS62420) - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. - */ - -/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ - -#include "dim2_hal.h" -#include "dim2_errors.h" -#include "dim2_reg.h" -#include <linux/stddef.h> - -/* - * The number of frames per sub-buffer for synchronous channels. - * Allowed values: 1, 2, 4, 8, 16, 32, 64. - */ -#define FRAMES_PER_SUBBUFF 16 - -/* - * Size factor for synchronous DBR buffer. - * Minimal value is 4*FRAMES_PER_SUBBUFF. - */ -#define SYNC_DBR_FACTOR (4u * (u16)FRAMES_PER_SUBBUFF) - -/* - * Size factor for isochronous DBR buffer. - * Minimal value is 3. - */ -#define ISOC_DBR_FACTOR 3u - -/* - * Number of 32-bit units for DBR map. - * - * 1: block size is 512, max allocation is 16K - * 2: block size is 256, max allocation is 8K - * 4: block size is 128, max allocation is 4K - * 8: block size is 64, max allocation is 2K - * - * Min allocated space is block size. - * Max possible allocated space is 32 blocks. - */ -#define DBR_MAP_SIZE 2 - -/* -------------------------------------------------------------------------- */ -/* not configurable area */ - -#define CDT 0x00 -#define ADT 0x40 -#define MLB_CAT 0x80 -#define AHB_CAT 0x88 - -#define DBR_SIZE (16 * 1024) /* specified by IP */ -#define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE) - -/* -------------------------------------------------------------------------- */ -/* generic helper functions and macros */ - -#define MLBC0_FCNT_VAL_MACRO(n) MLBC0_FCNT_VAL_ ## n ## FPSB -#define MLBC0_FCNT_VAL(fpsb) MLBC0_FCNT_VAL_MACRO(fpsb) - -static inline u32 bit_mask(u8 position) -{ - return (u32)1 << position; -} - -static inline bool dim_on_error(u8 error_id, const char *error_message) -{ - dimcb_on_error(error_id, error_message); - return false; -} - -/* -------------------------------------------------------------------------- */ -/* types and local variables */ - -struct lld_global_vars_t { - bool dim_is_initialized; - bool mcm_is_initialized; - struct dim2_regs *dim2; /* DIM2 core base address */ - u32 dbr_map[DBR_MAP_SIZE]; -}; - -static struct lld_global_vars_t g = { false }; - -/* -------------------------------------------------------------------------- */ - -static int dbr_get_mask_size(u16 size) -{ - int i; - - for (i = 0; i < 6; i++) - if (size <= (DBR_BLOCK_SIZE << i)) - return 1 << i; - return 0; -} - -/** - * Allocates DBR memory. - * @param size Allocating memory size. - * @return Offset in DBR memory by success or DBR_SIZE if out of memory. - */ -static int alloc_dbr(u16 size) -{ - int mask_size; - int i, block_idx = 0; - - if (size <= 0) - return DBR_SIZE; /* out of memory */ - - mask_size = dbr_get_mask_size(size); - if (mask_size == 0) - return DBR_SIZE; /* out of memory */ - - for (i = 0; i < DBR_MAP_SIZE; i++) { - u32 const blocks = (size + DBR_BLOCK_SIZE - 1) / DBR_BLOCK_SIZE; - u32 mask = ~((~(u32)0) << blocks); - - do { - if ((g.dbr_map[i] & mask) == 0) { - g.dbr_map[i] |= mask; - return block_idx * DBR_BLOCK_SIZE; - } - block_idx += mask_size; - /* do shift left with 2 steps in case mask_size == 32 */ - mask <<= mask_size - 1; - } while ((mask <<= 1) != 0); - } - - return DBR_SIZE; /* out of memory */ -} - -static void free_dbr(int offs, int size) -{ - int block_idx = offs / DBR_BLOCK_SIZE; - u32 const blocks = (size + DBR_BLOCK_SIZE - 1) / DBR_BLOCK_SIZE; - u32 mask = ~((~(u32)0) << blocks); - - mask <<= block_idx % 32; - g.dbr_map[block_idx / 32] &= ~mask; -} - -/* -------------------------------------------------------------------------- */ - -static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) -{ - dimcb_io_write(&g.dim2->MADR, ctr_addr); - - /* wait till transfer is completed */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) - continue; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ - - return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx); -} - -static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) -{ - enum { MADR_WNR_BIT = 31 }; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ - - if (mask[0] != 0) - dimcb_io_write(&g.dim2->MDAT0, value[0]); - if (mask[1] != 0) - dimcb_io_write(&g.dim2->MDAT1, value[1]); - if (mask[2] != 0) - dimcb_io_write(&g.dim2->MDAT2, value[2]); - if (mask[3] != 0) - dimcb_io_write(&g.dim2->MDAT3, value[3]); - - dimcb_io_write(&g.dim2->MDWE0, mask[0]); - dimcb_io_write(&g.dim2->MDWE1, mask[1]); - dimcb_io_write(&g.dim2->MDWE2, mask[2]); - dimcb_io_write(&g.dim2->MDWE3, mask[3]); - - dimcb_io_write(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr); - - /* wait till transfer is completed */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) - continue; - - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ -} - -static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value) -{ - u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; - - dim2_write_ctr_mask(ctr_addr, mask, value); -} - -static inline void dim2_clear_ctr(u32 ctr_addr) -{ - u32 const value[4] = { 0, 0, 0, 0 }; - - dim2_write_ctr(ctr_addr, value); -} - -static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type, - bool read_not_write, bool sync_mfe) -{ - u16 const cat = - (read_not_write << CAT_RNW_BIT) | - (ch_type << CAT_CT_SHIFT) | - (ch_addr << CAT_CL_SHIFT) | - (sync_mfe << CAT_MFE_BIT) | - (false << CAT_MT_BIT) | - (true << CAT_CE_BIT); - u8 const ctr_addr = cat_base + ch_addr / 8; - u8 const idx = (ch_addr % 8) / 2; - u8 const shift = (ch_addr % 2) * 16; - u32 mask[4] = { 0, 0, 0, 0 }; - u32 value[4] = { 0, 0, 0, 0 }; - - mask[idx] = (u32)0xFFFF << shift; - value[idx] = cat << shift; - dim2_write_ctr_mask(ctr_addr, mask, value); -} - -static void dim2_clear_cat(u8 cat_base, u8 ch_addr) -{ - u8 const ctr_addr = cat_base + ch_addr / 8; - u8 const idx = (ch_addr % 8) / 2; - u8 const shift = (ch_addr % 2) * 16; - u32 mask[4] = { 0, 0, 0, 0 }; - u32 value[4] = { 0, 0, 0, 0 }; - - mask[idx] = (u32)0xFFFF << shift; - dim2_write_ctr_mask(ctr_addr, mask, value); -} - -static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size, - u16 packet_length) -{ - u32 cdt[4] = { 0, 0, 0, 0 }; - - if (packet_length) - cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT); - - cdt[3] = - ((hw_buffer_size - 1) << CDT3_BD_SHIFT) | - (dbr_address << CDT3_BA_SHIFT); - dim2_write_ctr(CDT + ch_addr, cdt); -} - -static void dim2_clear_cdt(u8 ch_addr) -{ - u32 cdt[4] = { 0, 0, 0, 0 }; - - dim2_write_ctr(CDT + ch_addr, cdt); -} - -static void dim2_configure_adt(u8 ch_addr) -{ - u32 adt[4] = { 0, 0, 0, 0 }; - - adt[0] = - (true << ADT0_CE_BIT) | - (true << ADT0_LE_BIT) | - (0 << ADT0_PG_BIT); - - dim2_write_ctr(ADT + ch_addr, adt); -} - -static void dim2_clear_adt(u8 ch_addr) -{ - u32 adt[4] = { 0, 0, 0, 0 }; - - dim2_write_ctr(ADT + ch_addr, adt); -} - -static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr, - u16 buffer_size) -{ - u8 const shift = idx * 16; - - u32 mask[4] = { 0, 0, 0, 0 }; - u32 adt[4] = { 0, 0, 0, 0 }; - - mask[1] = - bit_mask(ADT1_PS_BIT + shift) | - bit_mask(ADT1_RDY_BIT + shift) | - (ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift)); - adt[1] = - (true << (ADT1_PS_BIT + shift)) | - (true << (ADT1_RDY_BIT + shift)) | - ((buffer_size - 1) << (ADT1_BD_SHIFT + shift)); - - mask[idx + 2] = 0xFFFFFFFF; - adt[idx + 2] = buf_addr; - - dim2_write_ctr_mask(ADT + ch_addr, mask, adt); -} - -static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr, - u16 buffer_size) -{ - u8 const shift = idx * 16; - - u32 mask[4] = { 0, 0, 0, 0 }; - u32 adt[4] = { 0, 0, 0, 0 }; - - mask[1] = - bit_mask(ADT1_RDY_BIT + shift) | - (ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift)); - adt[1] = - (true << (ADT1_RDY_BIT + shift)) | - ((buffer_size - 1) << (ADT1_BD_SHIFT + shift)); - - mask[idx + 2] = 0xFFFFFFFF; - adt[idx + 2] = buf_addr; - - dim2_write_ctr_mask(ADT + ch_addr, mask, adt); -} - -static void dim2_clear_ctram(void) -{ - u32 ctr_addr; - - for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++) - dim2_clear_ctr(ctr_addr); -} - -static void dim2_configure_channel( - u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size, - u16 packet_length, bool sync_mfe) -{ - dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length); - dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0, sync_mfe); - - dim2_configure_adt(ch_addr); - dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1, sync_mfe); - - /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr)); -} - -static void dim2_clear_channel(u8 ch_addr) -{ - /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); - - dim2_clear_cat(AHB_CAT, ch_addr); - dim2_clear_adt(ch_addr); - - dim2_clear_cat(MLB_CAT, ch_addr); - dim2_clear_cdt(ch_addr); -} - -/* -------------------------------------------------------------------------- */ -/* channel state helpers */ - -static void state_init(struct int_ch_state *state) -{ - state->request_counter = 0; - state->service_counter = 0; - - state->idx1 = 0; - state->idx2 = 0; - state->level = 0; -} - -/* -------------------------------------------------------------------------- */ -/* macro helper functions */ - -static inline bool check_channel_address(u32 ch_address) -{ - return ch_address > 0 && (ch_address % 2) == 0 && - (ch_address / 2) <= (u32)CAT_CL_MASK; -} - -static inline bool check_packet_length(u32 packet_length) -{ - u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR; - - if (packet_length <= 0) - return false; /* too small */ - - if (packet_length > max_size) - return false; /* too big */ - - if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK) - return false; /* too big */ - - return true; -} - -static inline bool check_bytes_per_frame(u32 bytes_per_frame) -{ - u16 const max_size = ((u16)CDT3_BD_MASK + 1u) / SYNC_DBR_FACTOR; - - if (bytes_per_frame <= 0) - return false; /* too small */ - - if (bytes_per_frame > max_size) - return false; /* too big */ - - return true; -} - -static inline u16 norm_ctrl_async_buffer_size(u16 buf_size) -{ - u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u; - - if (buf_size > max_size) - return max_size; - - return buf_size; -} - -static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length) -{ - u16 n; - u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; - - if (buf_size > max_size) - buf_size = max_size; - - n = buf_size / packet_length; - - if (n < 2u) - return 0; /* too small buffer for given packet_length */ - - return packet_length * n; -} - -static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) -{ - u16 n; - u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; - u32 const unit = bytes_per_frame * (u16)FRAMES_PER_SUBBUFF; - - if (buf_size > max_size) - buf_size = max_size; - - n = buf_size / unit; - - if (n < 1u) - return 0; /* too small buffer for given bytes_per_frame */ - - return unit * n; -} - -static void dim2_cleanup(void) -{ - /* disable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT); - - dim2_clear_ctram(); - - /* disable mlb_int interrupt */ - dimcb_io_write(&g.dim2->MIEN, 0); - - /* clear status for all dma channels */ - dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); - - /* mask interrupts for all channels */ - dimcb_io_write(&g.dim2->ACMR0, 0); - dimcb_io_write(&g.dim2->ACMR1, 0); -} - -static void dim2_initialize(bool enable_6pin, u8 mlb_clock) -{ - dim2_cleanup(); - - /* configure and enable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, - enable_6pin << MLBC0_MLBPEN_BIT | - mlb_clock << MLBC0_MLBCLK_SHIFT | - MLBC0_FCNT_VAL(FRAMES_PER_SUBBUFF) << MLBC0_FCNT_SHIFT | - true << MLBC0_MLBEN_BIT); - - /* activate all HBI channels */ - dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); - - /* enable HBI */ - dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); - - /* configure DMA */ - dimcb_io_write(&g.dim2->ACTL, - ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | - true << ACTL_SCE_BIT); -} - -static bool dim2_is_mlb_locked(void) -{ - u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT); - u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) | - bit_mask(MLBC1_LOCKERR_BIT); - u32 const c1 = dimcb_io_read(&g.dim2->MLBC1); - u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; - - dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask); - return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 && - (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0; -} - -/* -------------------------------------------------------------------------- */ -/* channel help routines */ - -static inline bool service_channel(u8 ch_addr, u8 idx) -{ - u8 const shift = idx * 16; - u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1); - - if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0) - return false; - - { - u32 mask[4] = { 0, 0, 0, 0 }; - u32 adt_w[4] = { 0, 0, 0, 0 }; - - mask[1] = - bit_mask(ADT1_DNE_BIT + shift) | - bit_mask(ADT1_ERR_BIT + shift) | - bit_mask(ADT1_RDY_BIT + shift); - dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); - } - - /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); - - return true; -} - -/* -------------------------------------------------------------------------- */ -/* channel init routines */ - -static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length) -{ - state_init(&ch->state); - - ch->addr = ch_addr; - - ch->packet_length = packet_length; - ch->bytes_per_frame = 0; - ch->done_sw_buffers_number = 0; -} - -static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame) -{ - state_init(&ch->state); - - ch->addr = ch_addr; - - ch->packet_length = 0; - ch->bytes_per_frame = bytes_per_frame; - ch->done_sw_buffers_number = 0; -} - -static void channel_init(struct dim_channel *ch, u8 ch_addr) -{ - state_init(&ch->state); - - ch->addr = ch_addr; - - ch->packet_length = 0; - ch->bytes_per_frame = 0; - ch->done_sw_buffers_number = 0; -} - -/* returns true if channel interrupt state is cleared */ -static bool channel_service_interrupt(struct dim_channel *ch) -{ - struct int_ch_state *const state = &ch->state; - - if (!service_channel(ch->addr, state->idx2)) - return false; - - state->idx2 ^= 1; - state->request_counter++; - return true; -} - -static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) -{ - struct int_ch_state *const state = &ch->state; - - if (buf_size <= 0) - return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size"); - - if (ch->packet_length == 0 && ch->bytes_per_frame == 0 && - buf_size != norm_ctrl_async_buffer_size(buf_size)) - return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, - "Bad control/async buffer size"); - - if (ch->packet_length && - buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length)) - return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, - "Bad isochronous buffer size"); - - if (ch->bytes_per_frame && - buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame)) - return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, - "Bad synchronous buffer size"); - - if (state->level >= 2u) - return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow"); - - ++state->level; - - if (ch->packet_length || ch->bytes_per_frame) - dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size); - else - dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr, - buf_size); - state->idx1 ^= 1; - - return true; -} - -static u8 channel_service(struct dim_channel *ch) -{ - struct int_ch_state *const state = &ch->state; - - if (state->service_counter != state->request_counter) { - state->service_counter++; - if (state->level == 0) - return DIM_ERR_UNDERFLOW; - - --state->level; - ch->done_sw_buffers_number++; - } - - return DIM_NO_ERROR; -} - -static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number) -{ - if (buffers_number > ch->done_sw_buffers_number) - return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow"); - - ch->done_sw_buffers_number -= buffers_number; - return true; -} - -/* -------------------------------------------------------------------------- */ -/* API */ - -u8 dim_startup(void *dim_base_address, u32 mlb_clock) -{ - g.dim_is_initialized = false; - - if (!dim_base_address) - return DIM_INIT_ERR_DIM_ADDR; - - /* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */ - /* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */ - if (mlb_clock >= 8) - return DIM_INIT_ERR_MLB_CLOCK; - - g.dim2 = dim_base_address; - g.dbr_map[0] = 0; - g.dbr_map[1] = 0; - - dim2_initialize(mlb_clock >= 3, mlb_clock); - - g.dim_is_initialized = true; - - return DIM_NO_ERROR; -} - -void dim_shutdown(void) -{ - g.dim_is_initialized = false; - dim2_cleanup(); -} - -bool dim_get_lock_state(void) -{ - return dim2_is_mlb_locked(); -} - -static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, - u16 ch_address, u16 hw_buffer_size) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - if (!check_channel_address(ch_address)) - return DIM_INIT_ERR_CHANNEL_ADDRESS; - - ch->dbr_size = hw_buffer_size; - ch->dbr_addr = alloc_dbr(ch->dbr_size); - if (ch->dbr_addr >= DBR_SIZE) - return DIM_INIT_ERR_OUT_OF_MEMORY; - - channel_init(ch, ch_address / 2); - - dim2_configure_channel(ch->addr, type, is_tx, - ch->dbr_addr, ch->dbr_size, 0, false); - - return DIM_NO_ERROR; -} - -u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) -{ - return norm_ctrl_async_buffer_size(buf_size); -} - -/** - * Retrieves maximal possible correct buffer size for isochronous data type - * conform to given packet length and not bigger than given buffer size. - * - * Returns non-zero correct buffer size or zero by error. - */ -u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length) -{ - if (!check_packet_length(packet_length)) - return 0; - - return norm_isoc_buffer_size(buf_size, packet_length); -} - -/** - * Retrieves maximal possible correct buffer size for synchronous data type - * conform to given bytes per frame and not bigger than given buffer size. - * - * Returns non-zero correct buffer size or zero by error. - */ -u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) -{ - if (!check_bytes_per_frame(bytes_per_frame)) - return 0; - - return norm_sync_buffer_size(buf_size, bytes_per_frame); -} - -u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 max_buffer_size) -{ - return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address, - max_buffer_size); -} - -u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 max_buffer_size) -{ - return init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address, - max_buffer_size); -} - -u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 packet_length) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - if (!check_channel_address(ch_address)) - return DIM_INIT_ERR_CHANNEL_ADDRESS; - - if (!check_packet_length(packet_length)) - return DIM_ERR_BAD_CONFIG; - - ch->dbr_size = packet_length * ISOC_DBR_FACTOR; - ch->dbr_addr = alloc_dbr(ch->dbr_size); - if (ch->dbr_addr >= DBR_SIZE) - return DIM_INIT_ERR_OUT_OF_MEMORY; - - isoc_init(ch, ch_address / 2, packet_length); - - dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr, - ch->dbr_size, packet_length, false); - - return DIM_NO_ERROR; -} - -u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 bytes_per_frame) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - if (!check_channel_address(ch_address)) - return DIM_INIT_ERR_CHANNEL_ADDRESS; - - if (!check_bytes_per_frame(bytes_per_frame)) - return DIM_ERR_BAD_CONFIG; - - ch->dbr_size = bytes_per_frame * SYNC_DBR_FACTOR; - ch->dbr_addr = alloc_dbr(ch->dbr_size); - if (ch->dbr_addr >= DBR_SIZE) - return DIM_INIT_ERR_OUT_OF_MEMORY; - - sync_init(ch, ch_address / 2, bytes_per_frame); - - dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx, - ch->dbr_addr, ch->dbr_size, 0, true); - - return DIM_NO_ERROR; -} - -u8 dim_destroy_channel(struct dim_channel *ch) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - dim2_clear_channel(ch->addr); - if (ch->dbr_addr < DBR_SIZE) - free_dbr(ch->dbr_addr, ch->dbr_size); - ch->dbr_addr = DBR_SIZE; - - return DIM_NO_ERROR; -} - -void dim_service_irq(struct dim_channel *const *channels) -{ - bool state_changed; - - if (!g.dim_is_initialized) { - dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, - "DIM is not initialized"); - return; - } - - if (!channels) { - dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels"); - return; - } - - /* - * Use while-loop and a flag to make sure the age is changed back at - * least once, otherwise the interrupt may never come if CPU generates - * interrupt on changing age. - * This cycle runs not more than number of channels, because - * channel_service_interrupt() routine doesn't start the channel again. - */ - do { - struct dim_channel *const *ch = channels; - - state_changed = false; - - while (*ch) { - state_changed |= channel_service_interrupt(*ch); - ++ch; - } - } while (state_changed); - - /* clear pending Interrupts */ - dimcb_io_write(&g.dim2->MS0, 0); - dimcb_io_write(&g.dim2->MS1, 0); -} - -u8 dim_service_channel(struct dim_channel *ch) -{ - if (!g.dim_is_initialized || !ch) - return DIM_ERR_DRIVER_NOT_INITIALIZED; - - return channel_service(ch); -} - -struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch, - struct dim_ch_state_t *state_ptr) -{ - if (!ch || !state_ptr) - return NULL; - - state_ptr->ready = ch->state.level < 2; - state_ptr->done_buffers = ch->done_sw_buffers_number; - - return state_ptr; -} - -bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, - u16 buffer_size) -{ - if (!ch) - return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, - "Bad channel"); - - return channel_start(ch, buffer_addr, buffer_size); -} - -bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number) -{ - if (!ch) - return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, - "Bad channel"); - - return channel_detach_buffers(ch, buffers_number); -} diff --git a/recipes-kernel/hdm-dim2/files/dim2_hal.h b/recipes-kernel/hdm-dim2/files/dim2_hal.h deleted file mode 100644 index 48cdd9c8c..000000000 --- a/recipes-kernel/hdm-dim2/files/dim2_hal.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * dim2_hal.h - DIM2 HAL interface - * (MediaLB, Device Interface Macro IP, OS62420) - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. - */ - -#ifndef _DIM2_HAL_H -#define _DIM2_HAL_H - -#include <linux/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * The values below are specified in the hardware specification. - * So, they should not be changed until the hardware specification changes. - */ -enum mlb_clk_speed { - CLK_256FS = 0, - CLK_512FS = 1, - CLK_1024FS = 2, - CLK_2048FS = 3, - CLK_3072FS = 4, - CLK_4096FS = 5, - CLK_6144FS = 6, - CLK_8192FS = 7, -}; - -struct dim_ch_state_t { - bool ready; /* Shows readiness to enqueue next buffer */ - u16 done_buffers; /* Number of completed buffers */ -}; - -typedef int atomic_counter_t; - -struct int_ch_state { - /* changed only in interrupt context */ - volatile atomic_counter_t request_counter; - - /* changed only in task context */ - volatile atomic_counter_t service_counter; - - u8 idx1; - u8 idx2; - u8 level; /* [0..2], buffering level */ -}; - -struct dim_channel { - struct int_ch_state state; - u8 addr; - u16 dbr_addr; - u16 dbr_size; - u16 packet_length; /*< Isochronous packet length in bytes. */ - u16 bytes_per_frame; /*< Synchronous bytes per frame. */ - u16 done_sw_buffers_number; /*< Done software buffers number. */ -}; - -u8 dim_startup(void *dim_base_address, u32 mlb_clock); - -void dim_shutdown(void); - -bool dim_get_lock_state(void); - -u16 dim_norm_ctrl_async_buffer_size(u16 buf_size); - -u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length); - -u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame); - -u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 max_buffer_size); - -u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 max_buffer_size); - -u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 packet_length); - -u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address, - u16 bytes_per_frame); - -u8 dim_destroy_channel(struct dim_channel *ch); - -void dim_service_irq(struct dim_channel *const *channels); - -u8 dim_service_channel(struct dim_channel *ch); - -struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch, - struct dim_ch_state_t *state_ptr); - -bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, - u16 buffer_size); - -bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); - -u32 dimcb_io_read(u32 *ptr32); - -void dimcb_io_write(u32 *ptr32, u32 value); - -void dimcb_on_error(u8 error_id, const char *error_message); - -#ifdef __cplusplus -} -#endif - -#endif /* _DIM2_HAL_H */ diff --git a/recipes-kernel/hdm-dim2/files/dim2_hdm.c b/recipes-kernel/hdm-dim2/files/dim2_hdm.c deleted file mode 100644 index 48ce7ab1b..000000000 --- a/recipes-kernel/hdm-dim2/files/dim2_hdm.c +++ /dev/null @@ -1,933 +0,0 @@ -/* - * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/printk.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/dma-mapping.h> -#include <linux/sched.h> -#include <linux/kthread.h> - -#include <mostcore.h> -#include <networking.h> -#include "dim2_hal.h" -#include "dim2_hdm.h" -#include "dim2_errors.h" -#include "dim2_sysfs.h" - -#define DMA_CHANNELS (32 - 1) /* channel 0 is a system channel */ - -#define MAX_BUFFERS_PACKET 32 -#define MAX_BUFFERS_STREAMING 32 -#define MAX_BUF_SIZE_PACKET 2048 -#define MAX_BUF_SIZE_STREAMING (8 * 1024) - -/* command line parameter to select clock speed */ -static char *clock_speed; -module_param(clock_speed, charp, 0); -MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed"); - -/* - * ############################################################################# - * - * The define below activates an utility function used by HAL-simu - * for calling DIM interrupt handler. - * It is used only for TEST PURPOSE and shall be commented before release. - * - * ############################################################################# - */ -/* #define ENABLE_HDM_TEST */ - -static DEFINE_SPINLOCK(dim_lock); - -static void dim2_tasklet_fn(unsigned long data); -static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0); - -/** - * struct hdm_channel - private structure to keep channel specific data - * @is_initialized: identifier to know whether the channel is initialized - * @ch: HAL specific channel data - * @pending_list: list to keep MBO's before starting transfer - * @started_list: list to keep MBO's after starting transfer - * @direction: channel direction (TX or RX) - * @data_type: channel data type - */ -struct hdm_channel { - char name[sizeof "caNNN"]; - bool is_initialized; - struct dim_channel ch; - struct list_head pending_list; /* before dim_enqueue_buffer() */ - struct list_head started_list; /* after dim_enqueue_buffer() */ - enum most_channel_direction direction; - enum most_channel_data_type data_type; -}; - -/** - * struct dim2_hdm - private structure to keep interface specific data - * @hch: an array of channel specific data - * @most_iface: most interface structure - * @capabilities: an array of channel capability data - * @io_base: I/O register base address - * @irq_ahb0: dim2 AHB0 irq number - * @clk_speed: user selectable (through command line parameter) clock speed - * @netinfo_task: thread to deliver network status - * @netinfo_waitq: waitq for the thread to sleep - * @deliver_netinfo: to identify whether network status received - * @mac_addrs: INIC mac address - * @link_state: network link state - * @atx_idx: index of async tx channel - */ -struct dim2_hdm { - struct hdm_channel hch[DMA_CHANNELS]; - struct most_channel_capability capabilities[DMA_CHANNELS]; - struct most_interface most_iface; - char name[16 + sizeof "dim2-"]; - void *io_base; - unsigned int irq_ahb0; - int clk_speed; - struct task_struct *netinfo_task; - wait_queue_head_t netinfo_waitq; - int deliver_netinfo; - unsigned char mac_addrs[6]; - unsigned char link_state; - int atx_idx; - struct medialb_bus bus; -}; - -#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface) - -/* Macro to identify a network status message */ -#define PACKET_IS_NET_INFO(p) \ - (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ - ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) - -#if defined(ENABLE_HDM_TEST) -static struct dim2_hdm *test_dev; -#endif - -bool dim2_sysfs_get_state_cb(void) -{ - bool state; - unsigned long flags; - - spin_lock_irqsave(&dim_lock, flags); - state = dim_get_lock_state(); - spin_unlock_irqrestore(&dim_lock, flags); - - return state; -} - -/** - * dimcb_io_read - callback from HAL to read an I/O register - * @ptr32: register address - */ -u32 dimcb_io_read(u32 *ptr32) -{ - return readl(ptr32); -} - -/** - * dimcb_io_write - callback from HAL to write value to an I/O register - * @ptr32: register address - * @value: value to write - */ -void dimcb_io_write(u32 *ptr32, u32 value) -{ - writel(value, ptr32); -} - -/** - * dimcb_on_error - callback from HAL to report miscommunication between - * HDM and HAL - * @error_id: Error ID - * @error_message: Error message. Some text in a free format - */ -void dimcb_on_error(u8 error_id, const char *error_message) -{ - pr_err("dimcb_on_error: error_id - %d, error_message - %s\n", error_id, - error_message); -} - -/** - * startup_dim - initialize the dim2 interface - * @pdev: platform device - * - * Get the value of command line parameter "clock_speed" if given or use the - * default value, enable the clock and PLL, and initialize the dim2 interface. - */ -static int startup_dim(struct platform_device *pdev) -{ - struct dim2_hdm *dev = platform_get_drvdata(pdev); - struct dim2_platform_data *pdata = pdev->dev.platform_data; - u8 hal_ret; - - dev->clk_speed = -1; - - if (clock_speed) { - if (!strcmp(clock_speed, "256fs")) - dev->clk_speed = CLK_256FS; - else if (!strcmp(clock_speed, "512fs")) - dev->clk_speed = CLK_512FS; - else if (!strcmp(clock_speed, "1024fs")) - dev->clk_speed = CLK_1024FS; - else if (!strcmp(clock_speed, "2048fs")) - dev->clk_speed = CLK_2048FS; - else if (!strcmp(clock_speed, "3072fs")) - dev->clk_speed = CLK_3072FS; - else if (!strcmp(clock_speed, "4096fs")) - dev->clk_speed = CLK_4096FS; - else if (!strcmp(clock_speed, "6144fs")) - dev->clk_speed = CLK_6144FS; - else if (!strcmp(clock_speed, "8192fs")) - dev->clk_speed = CLK_8192FS; - } - - if (dev->clk_speed == -1) { - pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n"); - dev->clk_speed = CLK_3072FS; - } else { - pr_info("Selected clock speed: %s\n", clock_speed); - } - if (pdata && pdata->init) { - int ret = pdata->init(pdata, dev->io_base, dev->clk_speed); - - if (ret) - return ret; - } - - hal_ret = dim_startup(dev->io_base, dev->clk_speed); - if (hal_ret != DIM_NO_ERROR) { - pr_err("dim_startup failed: %d\n", hal_ret); - if (pdata && pdata->destroy) - pdata->destroy(pdata); - return -ENODEV; - } - - return 0; -} - -/** - * try_start_dim_transfer - try to transfer a buffer on a channel - * @hdm_ch: channel specific data - * - * Transfer a buffer from pending_list if the channel is ready - */ -static int try_start_dim_transfer(struct hdm_channel *hdm_ch) -{ - u16 buf_size; - struct list_head *head = &hdm_ch->pending_list; - struct mbo *mbo; - unsigned long flags; - struct dim_ch_state_t st; - - BUG_ON(!hdm_ch); - BUG_ON(!hdm_ch->is_initialized); - - spin_lock_irqsave(&dim_lock, flags); - if (list_empty(head)) { - spin_unlock_irqrestore(&dim_lock, flags); - return -EAGAIN; - } - - if (!dim_get_channel_state(&hdm_ch->ch, &st)->ready) { - spin_unlock_irqrestore(&dim_lock, flags); - return -EAGAIN; - } - - mbo = list_entry(head->next, struct mbo, list); - buf_size = mbo->buffer_length; - - BUG_ON(mbo->bus_address == 0); - if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) { - list_del(head->next); - spin_unlock_irqrestore(&dim_lock, flags); - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - mbo->complete(mbo); - return -EFAULT; - } - - list_move_tail(head->next, &hdm_ch->started_list); - spin_unlock_irqrestore(&dim_lock, flags); - - return 0; -} - -/** - * deliver_netinfo_thread - thread to deliver network status to mostcore - * @data: private data - * - * Wait for network status and deliver it to mostcore once it is received - */ -static int deliver_netinfo_thread(void *data) -{ - struct dim2_hdm *dev = data; - - while (!kthread_should_stop()) { - wait_event_interruptible(dev->netinfo_waitq, - dev->deliver_netinfo || - kthread_should_stop()); - - if (dev->deliver_netinfo) { - dev->deliver_netinfo--; - most_deliver_netinfo(&dev->most_iface, dev->link_state, - dev->mac_addrs); - } - } - - return 0; -} - -/** - * retrieve_netinfo - retrieve network status from received buffer - * @dev: private data - * @mbo: received MBO - * - * Parse the message in buffer and get node address, link state, MAC address. - * Wake up a thread to deliver this status to mostcore - */ -static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo) -{ - u8 *data = mbo->virt_address; - u8 *mac = dev->mac_addrs; - - pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]); - dev->link_state = data[18]; - pr_info("NIState: %d\n", dev->link_state); - memcpy(mac, data + 19, 6); - pr_info("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - dev->deliver_netinfo++; - wake_up_interruptible(&dev->netinfo_waitq); -} - -/** - * service_done_flag - handle completed buffers - * @dev: private data - * @ch_idx: channel index - * - * Return back the completed buffers to mostcore, using completion callback - */ -static void service_done_flag(struct dim2_hdm *dev, int ch_idx) -{ - struct hdm_channel *hdm_ch = dev->hch + ch_idx; - struct dim_ch_state_t st; - struct list_head *head; - struct mbo *mbo; - int done_buffers; - unsigned long flags; - u8 *data; - - BUG_ON(!hdm_ch); - BUG_ON(!hdm_ch->is_initialized); - - spin_lock_irqsave(&dim_lock, flags); - - done_buffers = dim_get_channel_state(&hdm_ch->ch, &st)->done_buffers; - if (!done_buffers) { - spin_unlock_irqrestore(&dim_lock, flags); - return; - } - - if (!dim_detach_buffers(&hdm_ch->ch, done_buffers)) { - spin_unlock_irqrestore(&dim_lock, flags); - return; - } - spin_unlock_irqrestore(&dim_lock, flags); - - head = &hdm_ch->started_list; - - while (done_buffers) { - spin_lock_irqsave(&dim_lock, flags); - if (list_empty(head)) { - spin_unlock_irqrestore(&dim_lock, flags); - pr_crit("hard error: started_mbo list is empty whereas DIM2 has sent buffers\n"); - break; - } - - mbo = list_entry(head->next, struct mbo, list); - list_del(head->next); - spin_unlock_irqrestore(&dim_lock, flags); - - data = mbo->virt_address; - - if (hdm_ch->data_type == MOST_CH_ASYNC && - hdm_ch->direction == MOST_CH_RX && - PACKET_IS_NET_INFO(data)) { - retrieve_netinfo(dev, mbo); - - spin_lock_irqsave(&dim_lock, flags); - list_add_tail(&mbo->list, &hdm_ch->pending_list); - spin_unlock_irqrestore(&dim_lock, flags); - } else { - if (hdm_ch->data_type == MOST_CH_CONTROL || - hdm_ch->data_type == MOST_CH_ASYNC) { - u32 const data_size = - (u32)data[0] * 256 + data[1] + 2; - - mbo->processed_length = - min_t(u32, data_size, - mbo->buffer_length); - } else { - mbo->processed_length = mbo->buffer_length; - } - mbo->status = MBO_SUCCESS; - mbo->complete(mbo); - } - - done_buffers--; - } -} - -static struct dim_channel **get_active_channels(struct dim2_hdm *dev, - struct dim_channel **buffer) -{ - int idx = 0; - int ch_idx; - - for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) { - if (dev->hch[ch_idx].is_initialized) - buffer[idx++] = &dev->hch[ch_idx].ch; - } - buffer[idx++] = NULL; - - return buffer; -} - -/** - * dim2_tasklet_fn - tasklet function - * @data: private data - * - * Service each initialized channel, if needed - */ -static void dim2_tasklet_fn(unsigned long data) -{ - struct dim2_hdm *dev = (struct dim2_hdm *)data; - unsigned long flags; - int ch_idx; - - for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) { - if (!dev->hch[ch_idx].is_initialized) - continue; - - spin_lock_irqsave(&dim_lock, flags); - dim_service_channel(&dev->hch[ch_idx].ch); - spin_unlock_irqrestore(&dim_lock, flags); - - service_done_flag(dev, ch_idx); - while (!try_start_dim_transfer(dev->hch + ch_idx)) - continue; - } -} - -/** - * dim2_ahb_isr - interrupt service routine - * @irq: irq number - * @_dev: private data - * - * Acknowledge the interrupt and schedule a tasklet to service channels. - * Return IRQ_HANDLED. - */ -static irqreturn_t dim2_ahb_isr(int irq, void *_dev) -{ - struct dim2_hdm *dev = _dev; - struct dim_channel *buffer[DMA_CHANNELS + 1]; - unsigned long flags; - - spin_lock_irqsave(&dim_lock, flags); - dim_service_irq(get_active_channels(dev, buffer)); - spin_unlock_irqrestore(&dim_lock, flags); - -#if !defined(ENABLE_HDM_TEST) - dim2_tasklet.data = (unsigned long)dev; - tasklet_schedule(&dim2_tasklet); -#else - dim2_tasklet_fn((unsigned long)dev); -#endif - return IRQ_HANDLED; -} - -#if defined(ENABLE_HDM_TEST) - -/* - * Utility function used by HAL-simu for calling DIM interrupt handler. - * It is used only for TEST PURPOSE. - */ -void raise_dim_interrupt(void) -{ - (void)dim2_ahb_isr(0, test_dev); -} -#endif - -/** - * complete_all_mbos - complete MBO's in a list - * @head: list head - * - * Delete all the entries in list and return back MBO's to mostcore using - * completion call back. - */ -static void complete_all_mbos(struct list_head *head) -{ - unsigned long flags; - struct mbo *mbo; - - for (;;) { - spin_lock_irqsave(&dim_lock, flags); - if (list_empty(head)) { - spin_unlock_irqrestore(&dim_lock, flags); - break; - } - - mbo = list_entry(head->next, struct mbo, list); - list_del(head->next); - spin_unlock_irqrestore(&dim_lock, flags); - - mbo->processed_length = 0; - mbo->status = MBO_E_CLOSE; - mbo->complete(mbo); - } -} - -/** - * configure_channel - initialize a channel - * @iface: interface the channel belongs to - * @channel: channel to be configured - * @channel_config: structure that holds the configuration information - * - * Receives configuration information from mostcore and initialize - * the corresponding channel. Return 0 on success, negative on failure. - */ -static int configure_channel(struct most_interface *most_iface, int ch_idx, - struct most_channel_config *ccfg) -{ - struct dim2_hdm *dev = iface_to_hdm(most_iface); - bool const is_tx = ccfg->direction == MOST_CH_TX; - u16 const sub_size = ccfg->subbuffer_size; - u16 const buf_size = ccfg->buffer_size; - u16 new_size; - unsigned long flags; - u8 hal_ret; - int const ch_addr = ch_idx * 2 + 2; - struct hdm_channel *const hdm_ch = dev->hch + ch_idx; - - BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); - - if (hdm_ch->is_initialized) - return -EPERM; - - switch (ccfg->data_type) { - case MOST_CH_CONTROL: - new_size = dim_norm_ctrl_async_buffer_size(buf_size); - if (new_size == 0) { - pr_err("%s: too small buffer size\n", hdm_ch->name); - return -EINVAL; - } - ccfg->buffer_size = new_size; - if (new_size != buf_size) - pr_warn("%s: fixed buffer size (%d -> %d)\n", - hdm_ch->name, buf_size, new_size); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr, - buf_size); - break; - case MOST_CH_ASYNC: - new_size = dim_norm_ctrl_async_buffer_size(buf_size); - if (new_size == 0) { - pr_err("%s: too small buffer size\n", hdm_ch->name); - return -EINVAL; - } - ccfg->buffer_size = new_size; - if (new_size != buf_size) - pr_warn("%s: fixed buffer size (%d -> %d)\n", - hdm_ch->name, buf_size, new_size); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr, buf_size); - break; - case MOST_CH_ISOC_AVP: - new_size = dim_norm_isoc_buffer_size(buf_size, sub_size); - if (new_size == 0) { - pr_err("%s: invalid sub-buffer size or too small buffer size\n", - hdm_ch->name); - return -EINVAL; - } - ccfg->buffer_size = new_size; - if (new_size != buf_size) - pr_warn("%s: fixed buffer size (%d -> %d)\n", - hdm_ch->name, buf_size, new_size); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_isoc(&hdm_ch->ch, is_tx, ch_addr, sub_size); - break; - case MOST_CH_SYNC: - new_size = dim_norm_sync_buffer_size(buf_size, sub_size); - if (new_size == 0) { - pr_err("%s: invalid sub-buffer size or too small buffer size\n", - hdm_ch->name); - return -EINVAL; - } - ccfg->buffer_size = new_size; - if (new_size != buf_size) - pr_warn("%s: fixed buffer size (%d -> %d)\n", - hdm_ch->name, buf_size, new_size); - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_init_sync(&hdm_ch->ch, is_tx, ch_addr, sub_size); - break; - default: - pr_err("%s: configure failed, bad channel type: %d\n", - hdm_ch->name, ccfg->data_type); - return -EINVAL; - } - - if (hal_ret != DIM_NO_ERROR) { - spin_unlock_irqrestore(&dim_lock, flags); - pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n", - hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx); - return -ENODEV; - } - - hdm_ch->data_type = ccfg->data_type; - hdm_ch->direction = ccfg->direction; - hdm_ch->is_initialized = true; - - if (hdm_ch->data_type == MOST_CH_ASYNC && - hdm_ch->direction == MOST_CH_TX && - dev->atx_idx < 0) - dev->atx_idx = ch_idx; - - spin_unlock_irqrestore(&dim_lock, flags); - - return 0; -} - -/** - * enqueue - enqueue a buffer for data transfer - * @iface: intended interface - * @channel: ID of the channel the buffer is intended for - * @mbo: pointer to the buffer object - * - * Push the buffer into pending_list and try to transfer one buffer from - * pending_list. Return 0 on success, negative on failure. - */ -static int enqueue(struct most_interface *most_iface, int ch_idx, - struct mbo *mbo) -{ - struct dim2_hdm *dev = iface_to_hdm(most_iface); - struct hdm_channel *hdm_ch = dev->hch + ch_idx; - unsigned long flags; - - BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); - - if (!hdm_ch->is_initialized) - return -EPERM; - - if (mbo->bus_address == 0) - return -EFAULT; - - spin_lock_irqsave(&dim_lock, flags); - list_add_tail(&mbo->list, &hdm_ch->pending_list); - spin_unlock_irqrestore(&dim_lock, flags); - - (void)try_start_dim_transfer(hdm_ch); - - return 0; -} - -/** - * request_netinfo - triggers retrieving of network info - * @iface: pointer to the interface - * @channel_id: corresponding channel ID - * - * Send a command to INIC which triggers retrieving of network info by means of - * "Message exchange over MDP/MEP". Return 0 on success, negative on failure. - */ -static void request_netinfo(struct most_interface *most_iface, int ch_idx) -{ - struct dim2_hdm *dev = iface_to_hdm(most_iface); - struct mbo *mbo; - u8 *data; - - if (dev->atx_idx < 0) { - pr_err("Async Tx Not initialized\n"); - return; - } - - mbo = most_get_mbo(&dev->most_iface, dev->atx_idx, NULL); - if (!mbo) - return; - - mbo->buffer_length = 5; - - data = mbo->virt_address; - - data[0] = 0x00; /* PML High byte */ - data[1] = 0x03; /* PML Low byte */ - data[2] = 0x02; /* PMHL */ - data[3] = 0x08; /* FPH */ - data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */ - - most_submit_mbo(mbo); -} - -/** - * poison_channel - poison buffers of a channel - * @iface: pointer to the interface the channel to be poisoned belongs to - * @channel_id: corresponding channel ID - * - * Destroy a channel and complete all the buffers in both started_list & - * pending_list. Return 0 on success, negative on failure. - */ -static int poison_channel(struct most_interface *most_iface, int ch_idx) -{ - struct dim2_hdm *dev = iface_to_hdm(most_iface); - struct hdm_channel *hdm_ch = dev->hch + ch_idx; - unsigned long flags; - u8 hal_ret; - int ret = 0; - - BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); - - if (!hdm_ch->is_initialized) - return -EPERM; - - spin_lock_irqsave(&dim_lock, flags); - hal_ret = dim_destroy_channel(&hdm_ch->ch); - hdm_ch->is_initialized = false; - if (ch_idx == dev->atx_idx) - dev->atx_idx = -1; - spin_unlock_irqrestore(&dim_lock, flags); - if (hal_ret != DIM_NO_ERROR) { - pr_err("HAL Failed to close channel %s\n", hdm_ch->name); - ret = -EFAULT; - } - - complete_all_mbos(&hdm_ch->started_list); - complete_all_mbos(&hdm_ch->pending_list); - - return ret; -} - -/* - * dim2_probe - dim2 probe handler - * @pdev: platform device structure - * - * Register the dim2 interface with mostcore and initialize it. - * Return 0 on success, negative on failure. - */ -static int dim2_probe(struct platform_device *pdev) -{ - struct dim2_hdm *dev; - struct resource *res; - int ret, i; - struct kobject *kobj; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - dev->atx_idx = -1; - - platform_set_drvdata(pdev, dev); -#if defined(ENABLE_HDM_TEST) - test_dev = dev; -#else - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - pr_err("no memory region defined\n"); - ret = -ENOENT; - goto err_free_dev; - } - - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - pr_err("failed to request mem region\n"); - ret = -EBUSY; - goto err_free_dev; - } - - dev->io_base = ioremap(res->start, resource_size(res)); - if (!dev->io_base) { - pr_err("failed to ioremap\n"); - ret = -ENOMEM; - goto err_release_mem; - } - - ret = platform_get_irq(pdev, 0); - if (ret < 0) { - pr_err("failed to get irq\n"); - goto err_unmap_io; - } - dev->irq_ahb0 = ret; - - ret = request_irq(dev->irq_ahb0, dim2_ahb_isr, 0, "mlb_ahb0", dev); - if (ret) { - pr_err("failed to request IRQ: %d, err: %d\n", - dev->irq_ahb0, ret); - goto err_unmap_io; - } -#endif - init_waitqueue_head(&dev->netinfo_waitq); - dev->deliver_netinfo = 0; - dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev, - "dim2_netinfo"); - if (IS_ERR(dev->netinfo_task)) { - ret = PTR_ERR(dev->netinfo_task); - goto err_free_irq; - } - - for (i = 0; i < DMA_CHANNELS; i++) { - struct most_channel_capability *cap = dev->capabilities + i; - struct hdm_channel *hdm_ch = dev->hch + i; - - INIT_LIST_HEAD(&hdm_ch->pending_list); - INIT_LIST_HEAD(&hdm_ch->started_list); - hdm_ch->is_initialized = false; - snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2); - - cap->name_suffix = hdm_ch->name; - cap->direction = MOST_CH_RX | MOST_CH_TX; - cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | - MOST_CH_ISOC_AVP | MOST_CH_SYNC; - cap->num_buffers_packet = MAX_BUFFERS_PACKET; - cap->buffer_size_packet = MAX_BUF_SIZE_PACKET; - cap->num_buffers_streaming = MAX_BUFFERS_STREAMING; - cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING; - } - - { - const char *fmt; - - if (sizeof(res->start) == sizeof(long long)) - fmt = "dim2-%016llx"; - else if (sizeof(res->start) == sizeof(long)) - fmt = "dim2-%016lx"; - else - fmt = "dim2-%016x"; - - snprintf(dev->name, sizeof(dev->name), fmt, res->start); - } - - dev->most_iface.interface = ITYPE_MEDIALB_DIM2; - dev->most_iface.description = dev->name; - dev->most_iface.num_channels = DMA_CHANNELS; - dev->most_iface.channel_vector = dev->capabilities; - dev->most_iface.configure = configure_channel; - dev->most_iface.enqueue = enqueue; - dev->most_iface.poison_channel = poison_channel; - dev->most_iface.request_netinfo = request_netinfo; - - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { - ret = PTR_ERR(kobj); - pr_err("failed to register MOST interface\n"); - goto err_stop_thread; - } - - ret = dim2_sysfs_probe(&dev->bus, kobj); - if (ret) - goto err_unreg_iface; - - ret = startup_dim(pdev); - if (ret) { - pr_err("failed to initialize DIM2\n"); - goto err_destroy_bus; - } - - return 0; - -err_destroy_bus: - dim2_sysfs_destroy(&dev->bus); -err_unreg_iface: - most_deregister_interface(&dev->most_iface); -err_stop_thread: - kthread_stop(dev->netinfo_task); -err_free_irq: -#if !defined(ENABLE_HDM_TEST) - free_irq(dev->irq_ahb0, dev); -err_unmap_io: - iounmap(dev->io_base); -err_release_mem: - release_mem_region(res->start, resource_size(res)); -err_free_dev: -#endif - kfree(dev); - - return ret; -} - -/** - * dim2_remove - dim2 remove handler - * @pdev: platform device structure - * - * Unregister the interface from mostcore - */ -static int dim2_remove(struct platform_device *pdev) -{ - struct dim2_hdm *dev = platform_get_drvdata(pdev); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct dim2_platform_data *pdata = pdev->dev.platform_data; - unsigned long flags; - - spin_lock_irqsave(&dim_lock, flags); - dim_shutdown(); - spin_unlock_irqrestore(&dim_lock, flags); - - if (pdata && pdata->destroy) - pdata->destroy(pdata); - - dim2_sysfs_destroy(&dev->bus); - most_deregister_interface(&dev->most_iface); - kthread_stop(dev->netinfo_task); -#if !defined(ENABLE_HDM_TEST) - free_irq(dev->irq_ahb0, dev); - iounmap(dev->io_base); - release_mem_region(res->start, resource_size(res)); -#endif - kfree(dev); - platform_set_drvdata(pdev, NULL); - - /* - * break link to local platform_device_id struct - * to prevent crash by unload platform device module - */ - pdev->id_entry = NULL; - - return 0; -} - -static struct platform_device_id dim2_id[] = { - { "medialb_dim2" }, - { }, /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(platform, dim2_id); - -static struct platform_driver dim2_driver = { - .probe = dim2_probe, - .remove = dim2_remove, - .id_table = dim2_id, - .driver = { - .name = "hdm_dim2", - }, -}; - -module_platform_driver(dim2_driver); - -MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>"); -MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>"); -MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module"); -MODULE_LICENSE("GPL"); diff --git a/recipes-kernel/hdm-dim2/files/dim2_hdm.h b/recipes-kernel/hdm-dim2/files/dim2_hdm.h deleted file mode 100644 index 1c94e3355..000000000 --- a/recipes-kernel/hdm-dim2/files/dim2_hdm.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * dim2_hdm.h - MediaLB DIM2 HDM Header - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. - */ - -#ifndef DIM2_HDM_H -#define DIM2_HDM_H - -struct device; - -/* platform dependent data for dim2 interface */ -struct dim2_platform_data { - int (*init)(struct dim2_platform_data *pd, void *io_base, - int clk_speed); - void (*destroy)(struct dim2_platform_data *pd); - void *priv; -}; - -#endif /* DIM2_HDM_H */ diff --git a/recipes-kernel/hdm-dim2/files/dim2_reg.h b/recipes-kernel/hdm-dim2/files/dim2_reg.h deleted file mode 100644 index bcf6a79f6..000000000 --- a/recipes-kernel/hdm-dim2/files/dim2_reg.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * dim2_reg.h - Definitions for registers of DIM2 - * (MediaLB, Device Interface Macro IP, OS62420) - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. - */ - -#ifndef DIM2_OS62420_H -#define DIM2_OS62420_H - -#include <linux/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -struct dim2_regs { - /* 0x00 */ u32 MLBC0; - /* 0x01 */ u32 rsvd0[1]; - /* 0x02 */ u32 MLBPC0; - /* 0x03 */ u32 MS0; - /* 0x04 */ u32 rsvd1[1]; - /* 0x05 */ u32 MS1; - /* 0x06 */ u32 rsvd2[2]; - /* 0x08 */ u32 MSS; - /* 0x09 */ u32 MSD; - /* 0x0A */ u32 rsvd3[1]; - /* 0x0B */ u32 MIEN; - /* 0x0C */ u32 rsvd4[1]; - /* 0x0D */ u32 MLBPC2; - /* 0x0E */ u32 MLBPC1; - /* 0x0F */ u32 MLBC1; - /* 0x10 */ u32 rsvd5[0x10]; - /* 0x20 */ u32 HCTL; - /* 0x21 */ u32 rsvd6[1]; - /* 0x22 */ u32 HCMR0; - /* 0x23 */ u32 HCMR1; - /* 0x24 */ u32 HCER0; - /* 0x25 */ u32 HCER1; - /* 0x26 */ u32 HCBR0; - /* 0x27 */ u32 HCBR1; - /* 0x28 */ u32 rsvd7[8]; - /* 0x30 */ u32 MDAT0; - /* 0x31 */ u32 MDAT1; - /* 0x32 */ u32 MDAT2; - /* 0x33 */ u32 MDAT3; - /* 0x34 */ u32 MDWE0; - /* 0x35 */ u32 MDWE1; - /* 0x36 */ u32 MDWE2; - /* 0x37 */ u32 MDWE3; - /* 0x38 */ u32 MCTL; - /* 0x39 */ u32 MADR; - /* 0x3A */ u32 rsvd8[0xB6]; - /* 0xF0 */ u32 ACTL; - /* 0xF1 */ u32 rsvd9[3]; - /* 0xF4 */ u32 ACSR0; - /* 0xF5 */ u32 ACSR1; - /* 0xF6 */ u32 ACMR0; - /* 0xF7 */ u32 ACMR1; -}; - -#define DIM2_MASK(n) (~((~(u32)0) << (n))) - -enum { - MLBC0_MLBLK_BIT = 7, - - MLBC0_MLBPEN_BIT = 5, - - MLBC0_MLBCLK_SHIFT = 2, - MLBC0_MLBCLK_VAL_256FS = 0, - MLBC0_MLBCLK_VAL_512FS = 1, - MLBC0_MLBCLK_VAL_1024FS = 2, - MLBC0_MLBCLK_VAL_2048FS = 3, - - MLBC0_FCNT_SHIFT = 15, - MLBC0_FCNT_MASK = 7, - MLBC0_FCNT_VAL_1FPSB = 0, - MLBC0_FCNT_VAL_2FPSB = 1, - MLBC0_FCNT_VAL_4FPSB = 2, - MLBC0_FCNT_VAL_8FPSB = 3, - MLBC0_FCNT_VAL_16FPSB = 4, - MLBC0_FCNT_VAL_32FPSB = 5, - MLBC0_FCNT_VAL_64FPSB = 6, - - MLBC0_MLBEN_BIT = 0, - - MIEN_CTX_BREAK_BIT = 29, - MIEN_CTX_PE_BIT = 28, - MIEN_CTX_DONE_BIT = 27, - - MIEN_CRX_BREAK_BIT = 26, - MIEN_CRX_PE_BIT = 25, - MIEN_CRX_DONE_BIT = 24, - - MIEN_ATX_BREAK_BIT = 22, - MIEN_ATX_PE_BIT = 21, - MIEN_ATX_DONE_BIT = 20, - - MIEN_ARX_BREAK_BIT = 19, - MIEN_ARX_PE_BIT = 18, - MIEN_ARX_DONE_BIT = 17, - - MIEN_SYNC_PE_BIT = 16, - - MIEN_ISOC_BUFO_BIT = 1, - MIEN_ISOC_PE_BIT = 0, - - MLBC1_NDA_SHIFT = 8, - MLBC1_NDA_MASK = 0xFF, - - MLBC1_CLKMERR_BIT = 7, - MLBC1_LOCKERR_BIT = 6, - - ACTL_DMA_MODE_BIT = 2, - ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0, - ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1, - ACTL_SCE_BIT = 0, - - HCTL_EN_BIT = 15 -}; - -enum { - CDT1_BS_ISOC_SHIFT = 0, - CDT1_BS_ISOC_MASK = DIM2_MASK(9), - - CDT3_BD_SHIFT = 0, - CDT3_BD_MASK = DIM2_MASK(12), - CDT3_BD_ISOC_MASK = DIM2_MASK(13), - CDT3_BA_SHIFT = 16, - - ADT0_CE_BIT = 15, - ADT0_LE_BIT = 14, - ADT0_PG_BIT = 13, - - ADT1_RDY_BIT = 15, - ADT1_DNE_BIT = 14, - ADT1_ERR_BIT = 13, - ADT1_PS_BIT = 12, - ADT1_MEP_BIT = 11, - ADT1_BD_SHIFT = 0, - ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11), - ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13), - - CAT_MFE_BIT = 14, - - CAT_MT_BIT = 13, - - CAT_RNW_BIT = 12, - - CAT_CE_BIT = 11, - - CAT_CT_SHIFT = 8, - CAT_CT_VAL_SYNC = 0, - CAT_CT_VAL_CONTROL = 1, - CAT_CT_VAL_ASYNC = 2, - CAT_CT_VAL_ISOC = 3, - - CAT_CL_SHIFT = 0, - CAT_CL_MASK = DIM2_MASK(6) -}; - -#ifdef __cplusplus -} -#endif - -#endif /* DIM2_OS62420_H */ diff --git a/recipes-kernel/hdm-dim2/files/dim2_sysfs.c b/recipes-kernel/hdm-dim2/files/dim2_sysfs.c deleted file mode 100644 index c5b10c7d2..000000000 --- a/recipes-kernel/hdm-dim2/files/dim2_sysfs.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * dim2_sysfs.c - MediaLB sysfs information - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. - */ - -/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include "dim2_sysfs.h" - -struct bus_attr { - struct attribute attr; - ssize_t (*show)(struct medialb_bus *bus, char *buf); - ssize_t (*store)(struct medialb_bus *bus, const char *buf, - size_t count); -}; - -static ssize_t state_show(struct medialb_bus *bus, char *buf) -{ - bool state = dim2_sysfs_get_state_cb(); - - return sprintf(buf, "%s\n", state ? "locked" : ""); -} - -static struct bus_attr state_attr = __ATTR_RO(state); - -static struct attribute *bus_default_attrs[] = { - &state_attr.attr, - NULL, -}; - -static struct attribute_group bus_attr_group = { - .attrs = bus_default_attrs, -}; - -static void bus_kobj_release(struct kobject *kobj) -{ -} - -static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->show) - return -EIO; - - return xattr->show(bus, buf); -} - -static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - ssize_t ret; - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->store) - return -EIO; - - ret = xattr->store(bus, buf, count); - return ret; -} - -static struct sysfs_ops const bus_kobj_sysfs_ops = { - .show = bus_kobj_attr_show, - .store = bus_kobj_attr_store, -}; - -static struct kobj_type bus_ktype = { - .release = bus_kobj_release, - .sysfs_ops = &bus_kobj_sysfs_ops, -}; - -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj) -{ - int err; - - kobject_init(&bus->kobj_group, &bus_ktype); - err = kobject_add(&bus->kobj_group, parent_kobj, "bus"); - if (err) { - pr_err("kobject_add() failed: %d\n", err); - goto err_kobject_add; - } - - err = sysfs_create_group(&bus->kobj_group, &bus_attr_group); - if (err) { - pr_err("sysfs_create_group() failed: %d\n", err); - goto err_create_group; - } - - return 0; - -err_create_group: - kobject_put(&bus->kobj_group); - -err_kobject_add: - return err; -} - -void dim2_sysfs_destroy(struct medialb_bus *bus) -{ - kobject_put(&bus->kobj_group); -} diff --git a/recipes-kernel/hdm-dim2/files/dim2_sysfs.h b/recipes-kernel/hdm-dim2/files/dim2_sysfs.h deleted file mode 100644 index b71dd027e..000000000 --- a/recipes-kernel/hdm-dim2/files/dim2_sysfs.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * dim2_sysfs.h - MediaLB sysfs information - * - * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG - * - * 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. - * - * This file is licensed under GPLv2. - */ - -/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ - -#ifndef DIM2_SYSFS_H -#define DIM2_SYSFS_H - -#include <linux/kobject.h> - -struct medialb_bus { - struct kobject kobj_group; -}; - -struct dim2_hdm; - -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj); -void dim2_sysfs_destroy(struct medialb_bus *bus); - -/* - * callback, - * must deliver MediaLB state as true if locked or false if unlocked - */ -bool dim2_sysfs_get_state_cb(void); - -#endif /* DIM2_SYSFS_H */ diff --git a/recipes-kernel/hdm-dim2/hdm-dim2.bb b/recipes-kernel/hdm-dim2/hdm-dim2.bb index 438117a49..b51fe2362 100644 --- a/recipes-kernel/hdm-dim2/hdm-dim2.bb +++ b/recipes-kernel/hdm-dim2/hdm-dim2.bb @@ -1,31 +1,18 @@ DESCRIPTION = "Example of how to build an external Linux kernel module" LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://COPYING;md5=12f884d2ae1ff87c09e5b7ccc2c4ca7e \ - file://dim2_hdm.c;md5=263233c0fde1611b5b416f415bd3594d \ - file://dim2_hal.c;md5=9ae71bc76a4a056593eec2efc5703f50 \ - file://dim2_sysfs.c;md5=d66a0b6e9b3979d18653029d1cb4c362 \ - " +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" +#LIC_FILES_CHKSUM = "file://COPYING;md5=12f884d2ae1ff87c09e5b7ccc2c4ca7e \ +# " inherit module -PR = "r0" PV = "0.1" -SRC_URI = "file://Makefile \ - file://../../mostcore/files/mostcore.h \ - file://../../aim-network/files/networking.h \ - file://dim2_hal.h \ - file://dim2_hdm.h \ - file://dim2_sysfs.h \ - file://dim2_reg.h \ - file://dim2_errors.h \ - file://dim2_hdm.c \ - file://dim2_hal.c \ - file://dim2_sysfs.c \ - file://COPYING \ - " +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/most;protocol=https" -S = "${WORKDIR}" +S = "${WORKDIR}/git/driver/${PN}" +SRCREV = "ad245bdd60434dd46d6461f585d49db1b3b0d75b" +#SRCREV = "${AUTOREV}" # The inherit of module.bbclass will automatically name module packages with # "kernel-module-" prefix as required by the oe-core build environment. |